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
Exhaustive switch on a type union with a default case yields TS2339: Property 'x' does not exist on type 'never' #9838
typeTestType='foo'|'bar';interfaceTestInterface{type : TestType;}classTest{test=(param : TestInterface) : boolean=>{switch(param.type){case'foo' : returntrue;case'bar' : returnfalse;default : throwError("Invalid type: "+param.type);// TS2339: Property 'type' does not exist on type 'never'.}}}
Expected behavior:
The code compiles with no errors.
Actual behavior:
tsc test.ts
test.ts(14,53): error TS2339: Property 'type' does not exist on type 'never'.
I understand the compiler knows that with the current code the default case can never be reached and the type property can not have any possible valid TestType value in this case but the whole point of having a default case is to limit the scope of the human error, compiling with a different TS version, compiler flags etc. It can also be considered a safe coding practice.
The workaround is easy but ugly and should not be necessary:
The code above cannot go wrong in TypeScript land, as you have noted. The only reasonable error I can conceive is someone pass a value from the outside of TS or someone naughtily assert any.
In any case, I think your workaround is a good alarm of someone do wrong thing somewhere, though.
I dislike this current behavior. This should not be an error. It is quite weird TypeScript could change the type of an object (to never or anything else).
If you can't trust that the passed in param is really a TestInterface at runtime, then you probably shouldn't assume it's an object with a type property. If for example param is actually null or undefined, then the code above will throw a TypeError trying to access the type property. If it's a string or number, then it will throw "Invalid type: ".
Activity
HerringtonDarkholme commentedon Jul 20, 2016
The code above cannot go wrong in TypeScript land, as you have noted. The only reasonable error I can conceive is someone pass a value from the outside of TS or someone naughtily assert
any.In any case, I think your workaround is a good alarm of
someone do wrong thing somewhere, though.yahiko00 commentedon Jul 20, 2016
I dislike this current behavior. This should not be an error. It is quite weird TypeScript could change the type of an object (to
neveror anything else).yortus commentedon Jul 21, 2016
If you can't trust that the passed in
paramis really aTestInterfaceat runtime, then you probably shouldn't assume it's an object with atypeproperty. If for exampleparamis actuallynullorundefined, then the code above will throw aTypeErrortrying to access thetypeproperty. If it's a string or number, then it will throw"Invalid type: ".RyanCavanaugh commentedon Jul 21, 2016
Seems wrong --
paramshould be of typeTestInterfaceandparam.typeshould be of typeneverRyanCavanaugh commentedon Jul 22, 2016
Seems to be fixed in Anders' current literal types PR
ahejlsberg commentedon Aug 1, 2016
Fixed in #9407.