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
{{ message }}
Repository navigation
Type Narrowing for discriminated unions not narrow enough #12955
typeKinded={kind: 0}|{kind: 1}functionforKinded(k: Kinded){if(k.kind==0)console.log('ZERO')elseconsole.log('ONE')}constk={kind: 0}constk2: Kinded={kind: 0}forKinded(k)// nope. it has already guessed that k is of type { kind: number }forKinded(k2)// works. specifying type obviously does the right thingforKinded({kind: 0})// works. it understands that the argument literal is of type { kind: 0 }
Expected behavior:
Would expect it to try narrowing the type to a literal from the enumeration if the general enum doesn't satisfy other type expectations. Actual behavior:
When defined as a literal function argument, typescript further narrows the type, otherwise it does not? This seems perhaps non-awesome or at least the compiler maybe ought to try further narrowing as a constraint to see if it type-checks the entirety of the program?
Your last example works because the object literal is contextually typed by the parameter type. But in the first const k declaration there is nothing to indicate that you want kind to have a literal type so it is widened to number. It works when you have a type annotation because you're then contextually typed, just like the function call.
Narrowing further based on some use in another (perhaps remote) part of your program would be a non-local effect that has the potential to be very confusing (as in, why did my type all of a sudden switch to a literal type?). I don't think that is desirable.
Anders Hejlsberg (@ahejlsberg) Thanks for the response. I understand that feedback and pretty much assumed that was precisely what was happening. It seems possible to try narrowing the type being inferred to see if any narrower type satisfies the constraints of the program. I don't see how that would be "bad" behavior as if the type-checker ever manages to become fully satisfied I would see that as a win?
Specifically in the cases where there exist valid types in scope ( literals in this case ) that are narrower than the inferred type, it seems prudent to try them. Many javascript libraries would construct these literals and then use them later in the way I have shown in this example.
Activity
ahejlsberg commentedon Dec 15, 2016
Your last example works because the object literal is contextually typed by the parameter type. But in the first
const kdeclaration there is nothing to indicate that you wantkindto have a literal type so it is widened tonumber. It works when you have a type annotation because you're then contextually typed, just like the function call.Narrowing further based on some use in another (perhaps remote) part of your program would be a non-local effect that has the potential to be very confusing (as in, why did my type all of a sudden switch to a literal type?). I don't think that is desirable.
stevekane commentedon Dec 16, 2016
Anders Hejlsberg (@ahejlsberg) Thanks for the response. I understand that feedback and pretty much assumed that was precisely what was happening. It seems possible to try narrowing the type being inferred to see if any narrower type satisfies the constraints of the program. I don't see how that would be "bad" behavior as if the type-checker ever manages to become fully satisfied I would see that as a win?
Specifically in the cases where there exist valid types in scope ( literals in this case ) that are narrower than the inferred type, it seems prudent to try them. Many javascript libraries would construct these literals and then use them later in the way I have shown in this example.