-
Notifications
You must be signed in to change notification settings - Fork 12.5k
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
Type guard not work in union type of objects #30506
Comments
The type of Narrowing the parent object is only done in specific scenarios, when the property is considered a discriminant for the union. A property is considered as a discriminant property if:
Might be other scenarios that I haven't quoted here, but the scenario in the code is not covered by any as far as I can tell. As a side note, you can discriminated the union in the example using an function fn(i: { foo: string, bar: number, baz: boolean } | { foo: number, bar: boolean }) {
if ('baz' in i) {
i.foo // string
i.bar // number
}
} Or use a custom type guard. |
@dragomirtitian I have a question on why TS doesn't provide us the typeof guarding on codes above? Is there an underlying unsafe situation? |
@zheeeng These cases must be specifically crafted to work, they don't just happen. I am not sure there is a definitive answer as to why more cases are not considered as property discriminants but @ahejlsberg mentions in the original discriminated union PR in a response to a similar request to yours that:
Maybe someone in the team can tell us if this is still the definitive reason or there are other concerns. |
The lack of narrowing isn't because the type of |
As a newbie, this can be confusing. For example, when I look at this stackoverflow question, the code looks like it should compile (to me). The official documentation has a section for nearly every form of JavaScript "narrowing" I can think of. Then it goes even further, providing TypeScript-only solutions like Type Predicates. From my perspective, the most compelling reason to implement this is to make the language feel consistent. Currently, Now having said all that, I just wanted to answer your question since nobody else did. In my opinion, this might be more of a documentation issue than a problem with the language. And for that reason, I plan to open a separate issue. |
TypeScript Version: 3.3.3.3333
Search Terms:
type guard, union type of objects, typeof
Code
Code 2
Expected behavior:
in 'if' branch, ‘i’ should be { foo: string, bar: number, baz: boolean }
Actual behavior:
As comments says.
Playground Link:
http://www.typescriptlang.org/play/index.html#src=function%20fn(i%3A%20%7B%20foo%3A%20string%2C%20bar%3A%20number%2C%20baz%3A%20boolean%20%7D%20%7C%20%7B%20foo%3A%20number%2C%20bar%3A%20boolean%20%7D)%20%7B%0D%0A%20%20%20%20if%20(typeof%20i.foo%20%3D%3D%3D%20'string')%20%7B%0D%0A%20%20%20%20%20%20%20%20i.foo%20%2F%2F%20string%20%7C%20number%0D%0A%20%20%20%20%20%20%20%20i.bar%20%2F%2F%20number%20%7C%20boolean%0D%0A%20%20%20%20%7D%0D%0A%7D%0D%0A
The text was updated successfully, but these errors were encountered: