You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Infer keyword should work with unused generic type parameter of a superclass #40796
Possible, not pretty, but still usable workaround that solves this problem on the user code side is to add a property to the base class so that it will be used by compiler for type inference.
classA<T1,T2,T3>{readonlystub: T1={}asT1;}classB<T1,T2>extendsA<T1,T2,boolean>{}typeFirstAParam=B<string,number>extendsA<infer T1,any,any>// FirstAParam is string
? T1
: never;// ortypeFirstAParam2=B<string,number>['stub']// FirstAParam2 is string
changed the title [-]Infer keyword should work with generic type parameter of a superclass[/-][+]Infer keyword should work with unused generic type parameter of a superclass[/+]on Sep 27, 2020
This is working as intended. See this entry in the (somewhat outdated) FAQ. The type system is structural, not nominal; two types are the same iff they have the same structure or shape, not iff they have the same name or declaration.
In your code above, the type A<T1, T2, T3> is exactly the same as the empty object type {}. They are just two different names for the same type. To expect the compiler to be able to infer string from the type A<string, number, boolean> is to expect that it should be able to infer string from the type {}, which obviously doesn't work... just because the name you used to refer to {} mentioned string it doesn't imply that the type itself depends on string. (In practice the compiler sometimes does remember the name you used to refer to a type, and these in-principle-impossible inferences actually do happen; but you really can't rely on them.)
Your workaround is the recommended way to deal with cases like this: make sure your types are structurally dependent on the generic type parameters... the easiest way being to give them members of those types, like your stub. In any case this behavior is not a bug, but the expected behavior of TypeScript's structural type system.
It's a sort of sad because I have a complex scenario where one generic parameter of a class should be used later by class consumers, though there are no any properties of its type inside the class. OK, I understand, there is nothing to do except using the workaround :(
Activity
nicky1038 commentedon Sep 27, 2020
Possible, not pretty, but still usable workaround that solves this problem on the user code side is to add a property to the base class so that it will be used by compiler for type inference.
Playground link
[-]Infer keyword should work with generic type parameter of a superclass[/-][+]Infer keyword should work with unused generic type parameter of a superclass[/+]jcalz commentedon Sep 27, 2020
This is working as intended. See this entry in the (somewhat outdated) FAQ. The type system is structural, not nominal; two types are the same iff they have the same structure or shape, not iff they have the same name or declaration.
In your code above, the type
A<T1, T2, T3>is exactly the same as the empty object type{}. They are just two different names for the same type. To expect the compiler to be able to inferstringfrom the typeA<string, number, boolean>is to expect that it should be able to inferstringfrom the type{}, which obviously doesn't work... just because the name you used to refer to{}mentionedstringit doesn't imply that the type itself depends onstring. (In practice the compiler sometimes does remember the name you used to refer to a type, and these in-principle-impossible inferences actually do happen; but you really can't rely on them.)Your workaround is the recommended way to deal with cases like this: make sure your types are structurally dependent on the generic type parameters... the easiest way being to give them members of those types, like your
stub. In any case this behavior is not a bug, but the expected behavior of TypeScript's structural type system.nicky1038 commentedon Sep 27, 2020
Joe Calzaretta (@jcalz) Thank you for explanation and sorry for not reading the entire FAQ!
It's a sort of sad because I have a complex scenario where one generic parameter of a class should be used later by class consumers, though there are no any properties of its type inside the class. OK, I understand, there is nothing to do except using the workaround :(
BTW, in this case:
FirstAParamisstring, and it becomes a bit confusing why does this work one way in the first example and another way in this one.RyanCavanaugh commentedon Sep 28, 2020
Thanks Joe Calzaretta (@jcalz)
typescript-bot commentedon Sep 30, 2020
This issue has been marked 'Working as Intended' and has seen no recent activity. It has been automatically closed for house-keeping purposes.