Relationship between a TypeScript class and an interface with the same name Relationship between a TypeScript class and an interface with the same name typescript typescript

Relationship between a TypeScript class and an interface with the same name


Interfaces of the same name within a module will be merged:

interface Foo {    x: number;}interface Foo {    y: string;}let g = {} as Foo;g.x; // OKg.y; // OK

A class declaration creates both a constructor function as well as type declaration, which essentially means that all classes can be used as interfaces.

class Bar {    y: number;}interface IBaz extends Bar { } // includes y: numberclass CBaz implements Bar {    y: number = 5;}

Therefore, having a class and an interface with the same name is equivalent to having two interfaces with the same name, and you will get merge conflicts if both instances of the interface re-declare the same members with different types.

Strangely enough, Typescript will allow for this:

export interface Foo {    readonly x: number;}export class Foo {    readonly x: number = 3;}

but it won't allow get x() { return 3; } even though both of those generate as readonly x: number, so I can only imagine that the type checker considers them as different during merging even though they are semantically the same (this is why you can extend the interface and specify the readonly property as a getter function).


This is a limitation specific to accessors, and so far the Typescript team appears unwilling to comment on the issue.

class Foo {  readonly x: number = 0;}class Bar extends Foo {}interface Bar {  readonly x: 2;}const bar = new Bar();bar.x; // type is 2, no error

The team has commented that "[w]hether a property is implemented as a field or a getter/setter pair is an implementation detail, not part of the type," but this is clearly not the case as of Typescript 4.2:

class Baz extends Foo {    // error: "'x' is defined as a property in class 'Foo',    //         but is overridden here in 'Baz' as an accessor."    get x() {        return 2;    }}

I have no explanation for the team's responses. The comment that getters/setters are not part of the type system is from 2015 and may simply be outdated.