-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Infer types in unions #51349
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
Comments
Duplicate of #39065 (comment). This is very much intentional. The presence of a In your example of |
What about allowing use of if (a.foo!) {
console.log(a.foo)
} else {
console.log(a.bar)
} Since in the real world you end up doing this which is just as unsafe runtime and very inconvenient: if ((a as A).foo) {
console.log((a as A).foo)
} else {
console.log((a as B).bar)
} I've run into this recently both in the |
This is unreasonable. At the point of the operator the type is already known to not have a Also, this operator already has a meaning: It's the non-null assertion operator. It removes You already have a working solution: Using a type assertion (either to the specific type, or to |
I don't think that is unreasonable. I think the meaning is very similar to what the non-null assertion operator already does, it allows the developer to tell the compiler that they know what the type will be at this point. If it is too hard to implement at the end of the property access the meaning of |
The compiler checks, in order:
Again, this operator already has a meaning. Expanding on this with such an additional unsafe operation is really not desirable for most people. If at all, I could imagine something like I'm no member of the TypeScript team, I have no say, but I'm 99.99 % certain that this will be rejected. There is already a well working clean solution, and baking in syntax shortcuts for such a corner case is not practical. And this is a corner case, because usually you have a discriminator property. Anyway, I said my bits, I'm out. |
I disagree that this is such a corner case considering I've just run into it twice using two very popular libraries. But the workaround of |
@jnordberg interface A {
foo: string
}
interface B {
bar: string
}
type C = A | B
const a = {foo: ""} as C
if (a.foo) {
console.log(a.foo)
} else {
console.log(a.bar) // oops! not actually a B!
} |
@fatcerberus True, although it's more of a JavaScript footgun than a TypeScript one IMO. It would have made more sense to me if it inferred correctly when using |
FWIW, it’s actually an implicit design goal of the type system to save you from JS footguns and misfeatures, since you’re ultimately just writing JS-with-type-annotations. For instance, you can’t pass anything but a string to |
btw the reason |
Suggestion
This should work:
I think the compiler should be able to infer the types here. Its a very common pattern to return e.g. (SuccessResponse | ErrorResponse) and without inference it becomes very inconvenient to handle. I apologize if this has been discussed before, it seems like it should have been but I couldn't find anything with a quick search.
Playground
🔍 Search Terms
Infer union types
✅ Viability Checklist
My suggestion meets these guidelines:
The text was updated successfully, but these errors were encountered: