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
interfaceParent{children: Array<Child>}interfaceChild{type: 'child';}// the line below failsconstp1: Parent[]=[1].map(x=>({children: [{type: 'child'}]}))// the line below succeedsconstp2: Parent=({children: [{type: 'child'}]});
Error:
main.ts(66,7): error TS2322: Type '{ children: { type: string; }[]; }[]' is not assignable to type 'Parent[]'.
Type '{ children: { type: string; }[]; }' is not assignable to type 'Parent'.
Types of property 'children' are incompatible.
Type '{ type: string; }[]' is not assignable to type 'Child[]'.
Type '{ type: string; }' is not assignable to type 'Child'.
Types of property 'type' are incompatible.
Type 'string' is not assignable to type '"child"'.
How come p1 fails but p2 succeeds?
The text was updated successfully, but these errors were encountered:
Type argument inference is the process of figuring out which generics you meant to pass by diving into the arguments in a call.
Contextual typing is reaching up the tree from an expression to figure out where that expression might flow, in order to figure out what its type should be.
The way string literal types work is that a string literal expression must be contextually typed by a string literal type (or a union containing a string literal type) in order to type check as a string literal type instead of as string.
This means that in this example:
letx="foo";lety: "foo"="foo";
x will have type string but y will have type "foo" because the programmer made its type explicit and we can tell that "foo" will flow to a variable of type "foo".
In this case, what happens is that type argument inference occurs first. In your call to map, the compiler needs to figure out its type arguments. Recall that map is defined as something close to map<U>(callbackfn: (value: T) => U): U[]; for some Array<T>, so in order to figure out the type of U, we dive into its arguments. The only argument you gave map was the callback, so we try to type check the callback.
At this point, the callback is contextually typed, so we can infer the type of its parameter (which is great - that means you get intellisense that you want). We then kind of jump in and get the type of the returned expression which is { type: string }. That's when you get into a bad spot.
Now, the way you fixed your issue was by adding a return type to your callback. Pretty surprising, right? Basically one thing I didn't mention was that any returned expressions in functions are also contextually typed by the return type if it's known. In the last case it wasn't (we were trying to figure it out by type checking the callback, remember?), but in this case you made it explicit.
The fortunate part is that you can omit your type annotation for p1 since we'll have inferred it on our own.
I believe that if we had #3423, then this would work.
TS version 1.8.7
Error:
How come
p1
fails butp2
succeeds?The text was updated successfully, but these errors were encountered: