YES, it's possible. It requires some non-intuitive code but it will properly make sure you don't add redundant code.
You need the following line outside the class definition:
interface I {
a : string;
b : number;
c : string;
}
interface C extends I {}; //<--- this line
class C implements I {
constructor(data : I) {
this.a = data.a;
this.b = data.b;
this.c = data.c;
}
}
Playground Link
Now the TypeScript compiler will consider that the the class C has declared the same fields as the interface I.
It works like this:
interface C declares an interface called C.
extends I means it inherits the properties from the existing interface I.
{} is just the body of this interface C - it's empty, as we don't add or change anything.
On its own, it's not very impressive. However, there is already a class called C, so the interface with the same name refers to the same interface that the class has. In simple terms,
class A {
public foo: string;
constructor(data: string) {
this.foo = data;
}
}
compiles in JavaScript (target ES6+) to
class A {
constructor(data) {
this.foo = data;
}
}
the information removed pertains to the interface of the class that TypeScript will use at compile time to make sure you use the class correctly. For example:
- adding or referring to properties that aren't declared
- using the declared properties (like
foo: string) according to their type (e.g., not treating foo as a number).
- calling the constructor with the correct number and type of arguments
Declaring an interface with the same name of a class will instead merge the declaration with that of the class. This is why the class interface can be manipulated. And in this case, we use extends (which is valid for interfaces) to enrich the class definition (where only implements is allowed).
As a reference I got the technique from this comment in an issue thread for the TypeScript repository on GitHub. The title of the GitHub issue is "Class declarations should implicitly implement interfaces" and the comment is by RyanCavanaugh from 17th of February 2016:
Note that in the latest version of TypeScript, you can use class/interface merging to do this:
interface Foo {
a: number;
}
interface Baz extends Foo { }
class Baz {
constructor() {
console.log(this.a); // no error here
}
}
hat tip @jeffreymorlan for reminding me of this
[Note: the latest released version at the time of the comment would have been 1.8 Beta]