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
Search Terms:
lost generic types, generics property access, generic function invocation
Code:
declareconstabc: {a: {val: number,fn: (a: number)=>string},b: {val: string,fn: (a: boolean)=>number}};typeParam<Textends'a'|'b'>=Parameters<typeofabc[T]['fn']>[0];typeModel<Textends'a'|'b'>=ReturnType<typeofabc[T]['fn']>;consttester=<Textends'a'|'b'>(type: T,p: Param<T>)=>{consta=abc[type];// Generic is OK hereconstb=a.val;// Generic lost and becomes union :(constbb=a.valastypeofabc[T]['val'];// Explicit cast - Either number or string but in generic context// b expected to be bbconstc=a.fn// generic lost and becomes union :(constd=c(p);// accepts never and returns string | number - generic lost :(constcc=a.fnas(a: Param<T>)=>Model<T>;// Explicit castconstdd=cc(p);// Either number or string but in generic context// c expected to be cc}
Expected behavior:
The example is based on two problems which are essentially the same.
The first is more awkward - abc[type] retains the generic type and doesn't expand it,
while for some reason abc[type].val loses the generics. I would expect it to be the same type as doing typeof abc[T]['val']
especially when abc[type] works correctly.
The second example is concerning function invocation too but the problem's base is the same. When accessing abc[type].fn the generic type is lost and becomes a functions union which isn't invokable (parameter becomes never).
The wanted result is actually (a: Param<T>) => Model<T> retaining the generics and allowing invocation.
Actual behavior:
Concerning the function i kind of understand the design limitation but for abc[type].val it seems like a bug.
This is the intended behavior - lookup types are generally only preserved when it's not possible to resolve them through a constraint on that type parameter. The alternative universe where everything is processed in terms of deferred lookup types is really unpleasant to work in since there's no reasoning you can apply to a deferred operation. In general this only decreases completeness rather than inducing unsoundness, so overall it's a good compromise done on purpose.
@RyanCavanaugh But isn't it the idea of generics? I could pass a union directly and then handle the type problems with type casts. But i decided to go for generics saying that everything is based on it. I agree that those types can become ugly but maybe that's another point of how to display such types. The union fallback seems wrong... The only time i would expect it is if everything was the same type which means the generic parameter had no meaning anymore. But there is a big difference between string | number and the generic based type which i think worth it compared to type casts.
The behaviour here should be for regular union and not for generics imo. Or at least i should have a way to specify that this is what i mean to the compiler. Maybe both can be supported somehow based on the scenario?
TypeScript Version: 4.1.0-dev.20201015
Search Terms:
lost generic types, generics property access, generic function invocation
Code:
Expected behavior:
The example is based on two problems which are essentially the same.
The first is more awkward -
abc[type]
retains the generic type and doesn't expand it,while for some reason
abc[type].val
loses the generics. I would expect it to be the same type as doingtypeof abc[T]['val']
especially when
abc[type]
works correctly.The second example is concerning function invocation too but the problem's base is the same. When accessing
abc[type].fn
the generic type is lost and becomes a functions union which isn't invokable (parameter becomes never).The wanted result is actually
(a: Param<T>) => Model<T>
retaining the generics and allowing invocation.Actual behavior:
Concerning the function i kind of understand the design limitation but for
abc[type].val
it seems like a bug.Playground Link: https://www.typescriptlang.org/play?ts=4.1.0-dev.20201015#code/CYUwxgNghgTiAEYD2A7AzgF3lARmAXPAN4CwAUPNoaRZfAG5QSEoCuAtjiDADTl3wAZikIAKKCw5cYASngBeAHzxMMAJYoA5v3gBfPrRzUdlRsxUZ1WgwOFiJ8HEiQQQUFHKXw2nbjt3kugDc5OQYAJ4ADggACrBQ7AA8ACrwIAAeGCAowGjwAORQ+fAAPgU4+cry8HEwCSBZMGiJEdFIgth4ANrJALpd+cL5vYpdAAy9IWStCACySKAQKWmZ2bkFRaXllQrwAEoNrDAoyVEgLWftnWA9-YMow4pT5MjoWFmY3LvLGVk5eYVimV8hVFKIZoRkjx4JFCLUEilFJ5lDRKK9MNhdrgbjNJvAAPT4+AAcWy3DUYHgajyAHkANLwAAW3BAOnRWBwWIAdGYggSiaSUOTKRAkBj3MBHOAkOwQHlWCg1Kh4PhRGzUBicJzqlAeUxsHkZldsbcBmZhnzCfAAKLpSIQClqLBgKAYgC0NqdzJg3ikXyQPtUGk0jlYWA08E0ZPUlNeWUyOitnIy0TAWUlGCQUscOFCtHZiG5wn5kejFPgovFOSlyFl8sVytV6re8El1TAokiMktRKgYDAIEiGDyQvoXwl8DgGCO6AsVhDZR80ngHqjQpjFbFWCb+Y1zspOq5xdd8HEcPiSWSSIUynmi0RPZtdodYCdiFdGGbGOAbcQHa7j7Wl6XxLv6gaWMGobhigpbruWca-ImRKUim4DpvAmbZv2gTkEAA
Related Issues: #36737 (although seems the first part of mine isn't related)
The text was updated successfully, but these errors were encountered: