ProgrammingTypeScript Developer

What are Literal Types in TypeScript, and what are they used for? How can they be used to implement strict constraints on variable values and what traps exist when using them?

Pass interviews with Hintsage AI assistant

Answer

Literal Types allow you to restrict the possible values of a variable to only certain strict constants, rather than just a general type (for example, not just a number, but the number 5 or the string "yes").

This is useful for creating APIs with fixed parameters, statuses, etc.

type Direction = 'left' | 'right' | 'up' | 'down'; function move(dir: Direction) { // ... } move('left'); // OK move('top'); // Compilation error!

They also work with numbers, booleans, and even whole structures (tuple literal type):

type WeekDay = 1 | 2 | 3 | 4 | 5 | 6 | 7; const day: WeekDay = 6; // OK

Limitations and nuances:

  • Values cannot be implicitly cast to literal types (for example, you cannot assign a user input string to a variable of type 'left' | 'right' without a check).
  • When working with constants and let variables, it is important to remember the type inference:
const d = 'left'; // has type 'left' (Literal) let e = 'left'; // has type string (ordinary)

Trick question

Question: What type will a variable get if declared as const x = "yes"; — and can it later be assigned another string value?

Answer:

  • If you declare const x = "yes"; — x will have type "yes" (literal type), and it cannot be assigned any other value except 'yes' (and cannot be changed at all, because it is const).
  • If you declare let x = "yes";, then x will be typed as string, and any string values can be assigned to it.
const x = 'yes'; // x: 'yes' let y = 'yes'; // y: string

Examples of real errors due to a lack of knowledge about the nuances of the topic.


Story

In a task status project, an enum was used, but the developer replaced it with a string. As a result, the API began to accept any strings as a status, which led to many bugs during product development in production, as control was lost.


Story

A developer tried to use literal types for data validation but assigned parameters from a form field directly — TS allowed this because the input field type was string, not a literal (for example, "ok" | "fail"), since the input values were not validated. Consequently, at runtime, values appeared that were not from the set of allowed ones.


Story

While writing tests for a function that accepted literal values, an automatically generated test accidentally provided an unexpected string parameter, causing tests to fail. Later it turned out that the typing was weakened due to inattentiveness to type inference during let declaration, and this was not caught by the compiler.