Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Typescript: classes don't inherit types from interfaces? [duplicate]

Tags:

typescript

Why does the compiler implicit type casting not work for literal-typed properties which are implementations of an extended interface?

Example:

// typescript 3.4.5

interface INumContainer {
  num?: 1 | 2;
}

class myClass implements INumContainer {
  // does not compile
  // error TS2416: Property 'num' in type 'myClass' is not assignable to the same property in base type 'INumContainer'.
  //   Type 'number' is not assignable to type '1 | 2 | undefined'.
  num = 1;

  anotherNum: 1 | 2 = 1; // compiles
}
like image 848
habit Avatar asked Aug 01 '26 23:08

habit


1 Answers

Class members are not contextually typed by the types they are declared to extend or implement, at least as of TS3.7. The extends or implements declarations do result in type checking of the extending/implementing class, but this happens later. This has been a pain point for a long time.

What's happening here is that literal types like 1 or 2 are widened to containing types like number, unless they are in a non-widening context. And since myClass.num is not contextually typed by INumContainer["num"], it gets widened to number, which is seen to be incompatible.

The original issue filed about this for properties is microsoft/TypeScript#3667. There was an attempt to fix it, but it was eventually rejected/abandoned because of some poor interoperability with some real-world code libraries.

And not much has happened since. It seems that the currently open issue on this topic is microsoft/TypeScript#32082, so if you want to see this addressed you might want to go to that issue and give it a 👍 or some other show of support.

Until then, you'll just have to redundantly annotate your initializers. Sorry I don't have a better answer for you.

like image 194
jcalz Avatar answered Aug 04 '26 14:08

jcalz