| In the context of type definitions, strings aren't really regular bare strings. I.e. if I write type foo = {
bar: "Vodka"
}
I'm guaranteeing that the value of 'bar' on any object of that type must be "Vodka" - the type of bar is not string, it's literally "Vodka" because string values can be types.This seems a little obscure and pointless, but you can put these string types in a union, and enforce that a value must be one of many values. function doTheThing(color: "RED" | "GREEN") {
//do stuff
}
doTheThing("RED"); //ok
doTheThing("GREEN"); //ok
doTheThing("ORANGE"); //doesn't compile, because the type of the param *isn't* string, it's "RED" | "GREEN"
You can also define a type like type Mountain = { name: "EVEREST", height: 8848 } | { name: "K2", height: 8611 };
and then at compile time know that if mountain.name === "EVEREST" then height === 8848 because the types of name and height aren't string and number, they're "EVEREST" | "K2" and 8848 | 8611, and the compiler is smart enough to work out one based on the other.============================================== For extra context - a lot of this is for interoptability with Javascript code - you want to call some Javascript function with a stringly typed enum, and enforce only passing in valid values, but the Javascript code still just deals with strings. A lot of Typescripts kind of insane flexibility is so you can introduce type safety to all sorts of dynamic Javascript code, without having to make sacrifices on the dynamic-ness of it. Turns out this flexibility is actually kinda awesome to have in general even when you're not trying to refactor an existing JS codebase. |
```
type Color = "red" | "blue"; type Quantity = "one" | "two";
type SeussFish = `${Quantity | Color} fish`; // same as // type SeussFish = "one fish" | "two fish" // | "red fish" | "blue fish";
```