Reputation: 17
Typescript 3.5.3
{ sub: 123 }
infer as String when pass to a function with param type string | object
.
Example
function foo(bar: string | object) {
return 'test';
}
foo({ sub: 123 });
Error Message
error TS2326: Types of property 'sub' are incompatible.
Types of property 'sub' are incompatible.
Type 'number' is not assignable to type '(() => string) | undefined'.
I expect it infer as object
.
Upvotes: 0
Views: 77
Reputation: 329773
This is a known bug in TypeScript 3.5 which was introduced along with (generally) improved support for excess property checking in union types.
The problem here is that string
values have some deprecated HTML wrapper methods that output a version of the string surrounded by some HTML tags. One of them is sub
. Watch this craziness:
console.log("wat".sub()); // <sub>wat</sub>
The new excess property checking in TS3.5 looked at string | object
and the value {sub: 123}
and said, "well, string
has a sub
property of type ()=>string
, and object
doesn't have a known sub
property, so we will enforce excess property checking here by making object
's sub
property only accept undefined
. That means we need sub
to be of type (()=>string) | undefined
, and 123
doesn't match that. ERROR!"
For now, you will have to work around this with some sort of type widening or assertion:
foo({ toFixed: 123 } as object); // workaround in TS3.5
Luckily, it looks like this bug will be fixed in TypeScript 3.6. The fix is, I think, to simply ignore primitive types like string
in unions when doing excess property checking.
foo({ sub: 123 }); // error in TS3.5, okay in TS3.6
So your code will start working again. You can expect the following to continue to fail, though:
function baz(bar: { sub: () => string } | object) {
return 'test';
}
baz({ sub: 123 }); // error in TS3.5 and TS3.6
Okay; hope that helps. Good luck!
Upvotes: 1