I have the following common scenario in my TypeScript code:
interface TopLevelInterface<A extends BottomLevelInterface<B>, B>
and an implementation for BottomLevelInterface that looks like this:
class BottomLevelClass implements BottomLevelInterface<MyType>
My question is: When implementing TopLevelInterface I not only need to pass the type argument for A which would be BottomLevelClass, but also the second type argument for B which would be MyType in the above example.
Why do I need to specify B which could easily be inferred by looking at the type argument of BottomLevelClass ?
For example, when implementing TopLevelInterface I need to specify the following:
class TopLevelClass implements TopLevelInterface<ConcreteBottomLevel, MyType>
Instead of the shorter version that should be sufficient:
class TopLevelClass implements TopLevelInterface<ConcreteBottomLevel>
Why is this necessary? How can I infer the second type argument by looking at the first one? The only solution I came up with is using infer in TypeScript 2.8+ with a default assignment. This solution looks like this:
interface TopLevelInterface<A extends BottomLevelInterface<B>,
B = A extends BottomLevelInterface<infer _B> ? _B : any>
However, I'm not able to correctly apply this with a three-layer class hierarchy. In the following StackBlitz you can see that I cannot get the correct type constraint for the property model of TopLevelClass. It should be inferred to the type SomeType but instead is inferred to never. At MiddleLevelClass it does work correctly.
https://stackblitz.com/edit/typescript-pcxnzo?file=infer-generics.ts
Can anyone explain the issue or a better way to achieve the desired result?