Typescript: Union type allows any string value casted to an enum

Created on 17 Jan 2019  路  4Comments  路  Source: microsoft/TypeScript


TypeScript Version: 3.3.0-dev.20190117


Search Terms: enum, casting enum, union type

Code

 const enum Direction {                                                                                                                                                                  
     LEFT = "LEFT",                                                                                                                                                                      
     RIGHT = "RIGHT"                                                                                                                                                                     
 }                                                                                                                                                                                       

 type DirectionType = "UP" | "DOWN" | Direction;                                                                                                                                         

 const myDirection: DirectionType = <Direction>"SOUTHWEST"; // no warning or error                                                                                                         


Expected behavior:
Trying to assign "SOUTHWEST" to myDirection should give an error.

Actual behavior:
No warning or error.

All 4 comments

The behaviour here is correct and the reason you are seeing no error is because you are using a _cast_.

 <Direction>"SOUTHWEST";

If you remove the cast then you get the correct error:

const enum Direction {                                                                                                                                                                  
     LEFT = "LEFT",                                                                                                                                                                      
     RIGHT = "RIGHT"                                                                                                                                                                     
}

type DirectionType = "UP" | "DOWN" | Direction;                                                                                                                                                                                      

// Error Below
// Type '"SOUTHWEST"' is not assignable to type 'DirectionType'.                                                                                                                                                                                        
const myDirection: DirectionType = "SOUTHWEST"; 

For safe interaction you should only assign from a type with more information to a type with less information; casts lets you travel in the other direction, which is unsafe, but sometimes needed.

This is basically a duplicate of #14156

@jack-williams Problem is, casting is the first thing to come in mind to assign const enum to union type.
In case you want to assign "LEFT", you would just code:

const myDirection: DirectionType = "LEFT";

which is not working as it would accept only Direction.LEFT as a valid assignment. So _casting_ looks the closest cousin for that assignment. Since it is 'working' making a typo would get it unnoticed as you expect its type safety.

Feel free to close, but a warning, or some other kind of protection would be a lot beneficial.

@bariscicek

Feel free to close, but a warning, or some other kind of protection would be a lot beneficial.

Just an FYI: I have zero affiliation with the TypeScript team so it's not for me to pass final judgment, or close any issues.

@ajafff is right, this is pretty much a duplicate I think; specifically, the union type isn't really relevant here. You have the same issue with:

 const enum Direction {                                                                                                                                                                  
     LEFT = "LEFT",                                                                                                                                                                      
     RIGHT = "RIGHT"                                                                                                                                                                     
 }                                                                                                                                                                                                                                                                                                                                                                               
 type DirectionType = Direction; // NO UNION                                                                                                                                                                                                                                                                                                                                 
 const myDirection: DirectionType = <Direction>"SOUTHWEST"; // no warning or error

My opinion is that if something like this is a concern in your project, then a lint rule is the best way to go. I would suggest reading over the related issue (#14156) and if that doesn't answer all your questions, leave this issue open -- someone from the TS team can review it later.

Was this page helpful?
0 / 5 - 0 ratings