A literal is a more concrete sub-type of a collective type. What this means is that "Hello World" is a string, but a string is not "Hello World" inside the type system.

There are three sets of literal types available in TypeScript today: strings, numbers, and booleans; by using literal types you can allow an exact value which a string, number, or boolean must have.

Literal Narrowing

When you declare a variable via var or let, you are telling the compiler that there is the chance that this variable will change its contents. In contrast, using const to declare a variable will inform TypeScript that this object will never change.

  1. // We're making a guarantee that this variable
  2. // helloWorld will never change, by using const.
  3. // So, TypeScript sets the type to be "Hello World" not string
  4. const helloWorld = "Hello World";
  5. // On the other hand, a let can change, and so the compiler declares it a string
  6. let hiWorld = "Hi World";Try

The process of going from an infinite number of potential cases (there are an infinite number of possible string values) to a smaller, finite number of potential case (in helloWorld’s case: 1) is called narrowing.

String Literal Types

In practice string literal types combine nicely with union types, type guards, and type aliases. You can use these features together to get enum-like behavior with strings.

  1. type Easing = "ease-in" | "ease-out" | "ease-in-out";
  2. class UIElement {
  3. animate(dx: number, dy: number, easing: Easing) {
  4. if (easing === "ease-in") {
  5. // ...
  6. } else if (easing === "ease-out") {
  7. } else if (easing === "ease-in-out") {
  8. } else {
  9. // It's possible that someone could reach this
  10. // by ignoring your types though.
  11. }
  12. }
  13. }
  14. let button = new UIElement();
  15. button.animate(0, 0, "ease-in");
  16. button.animate(0, 0, "uneasy");
  17. Argument of type '"uneasy"' is not assignable to parameter of type 'Easing'.2345Argument of type '"uneasy"' is not assignable to parameter of type 'Easing'.Try

You can pass any of the three allowed strings, but any other string will give the error

  1. Argument of type '"uneasy"' is not assignable to parameter of type '"ease-in" | "ease-out" | "ease-in-out"'

String literal types can be used in the same way to distinguish overloads:

  1. function createElement(tagName: "img"): HTMLImageElement;
  2. function createElement(tagName: "input"): HTMLInputElement;
  3. // ... more overloads ...
  4. function createElement(tagName: string): Element {
  5. // ... code goes here ...
  6. }

Numeric Literal Types

TypeScript also has numeric literal types, which act the same as the string literals above.

  1. function rollDice(): 1 | 2 | 3 | 4 | 5 | 6 {
  2. return (Math.floor(Math.random() * 6) + 1) as 1 | 2 | 3 | 4 | 5 | 6;
  3. }
  4. const result = rollDice();Try

A common case for their use is for describing config values:

  1. interface MapConfig {
  2. lng: number;
  3. lat: number;
  4. tileSize: 8 | 16 | 32;
  5. }
  6. setupMap({ lng: -73.935242, lat: 40.73061, tileSize: 16 });Try

Boolean Literal Types

TypeScript also has boolean literal types. You might use these to constrain object values whose properties are interrelated.

  1. interface ValidationSuccess {
  2. isValid: true;
  3. reason: null;
  4. };
  5. interface ValidationFailure {
  6. isValid: false;
  7. reason: string;
  8. };
  9. type ValidationResult =
  10. | ValidationSuccess
  11. | ValidationFailure;Try