Typescript types don't compute
-
I ran into a typing problem after upgrading a library. This is the distilled form of the bug:
class Bar { id: string = ''; } declare type ExcludeFunctions<T, K extends keyof T> = T[K] extends Function ? never : (K extends symbol ? never : K); declare type Baz<T> = { [K in keyof T as ExcludeFunctions<T, K>]?: T[K]; }; class Base<T extends Bar> { public async foo(input: Baz<T>) { //Property 'id' does not exist on type 'Baz<T>'. input.id = 'x'; } }
Why doesn't Baz<Bar> have property 'id'? It looks like "string extends Function" evaluates to true, because when I remove this condition the error disappears. But string clearly doesn't extend Function. What is going on here?
-
@sebastian-galczynski I don't see what establishes Baz<T> as being an instance of Base<T>
-
@Gribnit said in Typescript types don't compute:
@sebastian-galczynski I don't see what establishes Baz<T> as being an instance of Base<T>
@Gribnit Nothing. I don't expect it to be. The problem is that type Baz<T>, where T extends Bar, doesn't have property id, while by my reasoning it should.
-
By comparison, this works:
class Bar { id: string = ''; } declare type ExcludeFunctions<T, K extends keyof T> = K extends symbol ? never : K; declare type Baz<T> = { [K in keyof T as ExcludeFunctions<T, K>]?: T[K]; }; class Base<T extends Bar> { public async foo(input: Baz<T>) { input.id = 'x'; } }
Which to me seems to imply that string extends Function, which is false.
-
@sebastian-galczynski I don't see how T for Baz would be the same as T for Base, so T in Baz doesn't seem to imply Bar. Am I missing a type definition fixing T?, or does Typescript make T consistent automagically? Looks like distinct generic types from here.
-
@Gribnit said in Typescript types don't compute:
Am I missing a type definition fixing T?
Yes. T in the method definition is the same T as in the class definition. The second example wouldn't work otherwise.
-
@sebastian-galczynski OK, I fold. I only understand Java generics.
-
@sebastian-galczynski said in Typescript types don't compute:
I ran into a typing problem after upgrading a library.
Well, then stop exploring the Carpal Tunnels of Alexandria.
This is the distilled form of the bug:
-
@sebastian-galczynski said in Typescript types don't compute:
[code snipped]Why doesn't Baz<Bar> have property 'id'? It looks like "string extends Function" evaluates to true, because when I remove this condition the error disappears. But string clearly doesn't extend Function. What is going on here?
It looks to me like
Baz<T extends Bar>.id
should exist, I think, if I'm following the generics instantiations correctly.
-
@sebastian-galczynski said in Typescript types don't compute:
@Gribnit said in Typescript types don't compute:
Am I missing a type definition fixing T?
Yes. T in the method definition is the same T as in the class definition. The second example wouldn't work otherwise.
I think he means all the
T
s through the whole file.@Gribnit, to answer your question, I think it could be re-written like so:
class Bar { id: string = ''; } declare type ExcludeFunctions<efT, efK extends keyof efT> = efT[efK] extends Function ? never : (efK extends symbol ? never : efK); declare type Baz<bT> = { [bK in keyof bT as ExcludeFunctions<bT, bK>]?: bT[bK]; }; class Base<baseT extends Bar> { public async foo(input: Baz<baseT>) { //Property 'id' does not exist on type 'Baz<baseT>'. input.id = 'x'; } }
@sebastian-galczynski, does the fact that the property in
Baz
is optional make a difference?