Home > database >  How to properly work with literal types in TypeScript?
How to properly work with literal types in TypeScript?

Time:11-26

I am trying to learn TS for the first time, but there is one case, which does not click quite well in my mind. Let's say we have two variables:

let value1: 'POST' | number | boolean = 'POST';
let value2: 'POST' | number | boolean | string = 'POST';

And let's say we have another variable to which we want to assign one of the variables specified above:

let copiedValue: 'POST'

When I assign to the variable copiedValue variable labeled value1 it works okay, but when I attempt to assign value2 complier shows me an error and I have to cast it to get rid of this error. I suppose that is because of additional string type that I added to value2 variable and TS compiler just warns that if something is labeled as a string it can be anything and not only 'POST', but is not it a problem that value1 variable has boolean and numeric types set on it too? Also, if TS compiler allows value1 because it knows that this variable holds "POST" at the moment of assignment to copiedValue variable, what is a problem with value2 variable if it also holds absolutely the same "POST" value?

CodePudding user response:

is not it a problem that value1 variable has boolean and numeric types set on it too?

In general, yes it is.

However, in your case you have assigned 'POST' to value1. This allows the compiler to infer that, at that point in the program, until something else is done with value1, it is of type 'POST'. With the type so inferred, assignment to copiedValue is permissible.

Try initialising value1 with value false and you will see that you get an error.

Also, if TS compiler allows value1 because it knows that this variable holds "POST" at the moment of assignment to copiedValue variable, what is a problem with value2 variable if it also holds absolutely the same "POST" value?

In the case of value2, the added type string means that, under the rules of the compiler, it cannot be determined whether value2 is of type 'POST' or string at the relevant point in the code. The compiler would not appear to be sophisticated enough to do that.

For the compiler to do that it would require it checking that no manipulation of the string contents of the value of value2 had not been done (eg to add a character to turn its value from 'POST' into 'POSTS'). It's easy to imagine that adding such a feature is not a priority of the TypeScript team.

CodePudding user response:

If copiedValue is of type 'POST', that's the only value it can accept. You shouldn't be able to assign value1 or value2 to it as far as type is concerned.

Typescript may be smart enough to see that in this particular case, value1 is explicitly assigned the value 'POST' and so it can safely assign it to copiedValue regardless, but that would just be a convenience it's giving you since the value is known at compile time.

Yes I think you're right that it's not able to do that in the case of value2 because there's ambiguity there as to whether 'POST' should be considered type 'POST' or type string.

Generally, typing anything 'EXPLICIT STRING HERE' | string is going to give you these kinds of problems. I would say in (nearly?) every case, you want to enumerate all possible string values or type something as string, but not both.

  • Related