-
Notifications
You must be signed in to change notification settings - Fork 12.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Unable to discriminate union type because of "Property does not exist" #28138
Comments
This should work function fn(baz: { foo: Foo; bar: string; } | { foo: Bar; })
{
if ("bar" in baz)
{
testFoo(baz.foo);
}
} With this PR #27695 you can also do this: function fn(baz: { foo: Foo; bar: string; } | { foo: Bar; bar: undefined })
{
if (baz.bar !== 'undefined')
{
testFoo(baz.foo);
}
} |
@jack-williams Your suggestion works. Thank you! I'll keep this issue open as I think it should be documented and/or we could have better syntax for it... but I might be wrong. I'd like a member of TS team to have a look and provide a definitive decision on that if you don't mind... |
Yep, with what we have in |
BTW, there's a good reason this: function fn(baz: { foo: Foo; bar: string; } | { foo: Bar; })
{
if (typeof baz.bar != 'undefined')
{
testFoo(baz.foo);
}
} doesn't work - consider this call: fn({bar: 12, foo: new Bar()}); that's a valid call (assignable to the second union member), and is why even if you were to check that |
Indeed. I haven't thought of this case. Thanks for your answer! |
…fering properties microsoft/TypeScript#28138 - need to explicitly mark properties as optional and undefined if they only appear on a subset of a union's possibilities
…fering properties microsoft/TypeScript#28138 - need to explicitly mark properties as optional and undefined if they only appear on a subset of a union's possibilities
Hi, I strolled by this thread randomly and I am immediately baffled as to why
And I tested it, indeed But then here comes the weird part:
But since reality doesn't agree with me, it must be I'm understanding union types wrong, or maybe TS has a bug. So if I were to guess, it seems that TS is pulling the P.S. there is more craziness. now try |
This is the wrong bit -- extra fields are allowed when there is some matching property in the target across any union member. |
Yeah, about that. That was my initial feeling so I did some more testing which ended up contradicting this. declare function id_or_name(input: {id:number; name:"joe"}|{name:string}): void
id_or_name({id:3, name:"alex"}) // Argument of type '{ id: number; name: string; }' is not assignable to parameter of type '{ id: number; name: "joe"; } | { name: string; }'. Object literal may only specify known properties, and 'id' does not exist in type '{ name: string; }'.ts(2345) Somehow this time it doesn't work again. I notice though that if instead of having declare function id_or_name(input: {id:number; name:Date}|{name:string}): void
id_or_name({id:3, name:"alex"}) // no problem |
TypeScript Version: typescript@3.2.0-dev.20181025
Search Terms: union narrowing discriminate missing property field
Code
Expected behavior:
No Error. I can call
testFoo(baz.foo)
since the union type is properly narrowed.Actual behavior:
Property 'bar' does not exist on type 'Baz'.
Argument of type 'Foo | Bar' is not assignable to parameter of type 'Foo'.
Type 'Bar' is not assignable to type 'Foo'.
Property 'foo' is missing in type 'Bar'.
Playground Link: https://www.typescriptlang.org/play/index.html#src=class%20Foo%0D%0A%7B%0D%0A%20%20%20%20private%20foo%3A%20string%3B%0D%0A%7D%0D%0A%0D%0Aclass%20Bar%0D%0A%7B%0D%0A%20%20%20%20private%20bar%3A%20number%3B%0D%0A%7D%0D%0A%0D%0Afunction%20fn(baz%3A%20%7B%20foo%3A%20Foo%3B%20bar%3A%20string%3B%20%7D%20%7C%20%7B%20foo%3A%20Bar%3B%20%7D)%0D%0A%7B%0D%0A%20%20%20%20if%20(typeof%20baz.bar%20!%3D%20'undefined')%0D%0A%20%20%20%20%7B%0D%0A%20%20%20%20%20%20%20%20testFoo(baz.foo)%3B%0D%0A%20%20%20%20%7D%0D%0A%7D%0D%0A%0D%0Afunction%20testFoo(foo%3A%20Foo)%0D%0A%7B%0D%0A%7D
Related Issues: I've looked around but found none.
Although, in general, I do understand this should not work, I think it would help greatly if we had a way to discriminate on properties that are only in some of the members of a union.
One of the solutions could be to type properties, that are missing in some of the union members as
prop?: void
, orprop?: never
, orprop?: undefined
, or whatever makes sense in the type system.The text was updated successfully, but these errors were encountered: