Execute Program

TypeScript Basics: Literal Types

Welcome to the Literal Types lesson!

This lesson is shown as static text below. However, it's designed to be used interactively. Click the button below to start!

  • We've seen basic types like number and string. Every concrete number and every concrete string is also a type. For example, a variable of type 1 can only hold the number 1. It can't hold 2; that's a compile-time type error.

  • >
    let one: 1 = 1;
    one;
    Result:
    1Pass Icon
  • >
    let one: 1 = 2;
    one;
    Result:
    type error: Type '2' is not assignable to type '1'.Pass Icon
  • >
    let one: 1 = 'one';
    one;
    Result:
    type error: Type '"one"' is not assignable to type '1'.Pass Icon
  • These are called literal types. For example, the type 1 above is a literal number type. We can combine literal types with unions to allow only certain values.

  • >
    let oneOrTwo: 1 | 2 = 1;
    oneOrTwo;
    Result:
    1Pass Icon
  • >
    let oneOrTwo: 1 | 2 = 2;
    oneOrTwo;
    Result:
    2Pass Icon
  • >
    let oneOrTwo: 1 | 2 = 3;
    oneOrTwo;
    Result:
    type error: Type '3' is not assignable to type '1 | 2'.Pass Icon
  • This seems like a strange feature at first, and most statically typed programming languages don't support it. However, it's very useful in practice and is used often in real-world TypeScript code.

  • For example, maybe we have a sort function. It can sort in either ascending ('asc') or descending ('desc') order.

  • >
    function sort2(numbers: number[], direction: 'asc' | 'desc'): number[] {
    const sortable = numbers.slice(); // Clone the array.
    sortable.sort();
    if (direction === 'desc') {
    sortable.reverse();
    }
    return sortable;
    }
  • Note: this code example reuses elements (variables, etc.) defined in earlier examples.
    >
    sort2([2, 1, 3], 'asc');
    Result:
    [1, 2, 3]Pass Icon
  • Note: this code example reuses elements (variables, etc.) defined in earlier examples.
    >
    sort2([2, 1, 3], 'desc');
    Result:
    [3, 2, 1]Pass Icon
  • Note: this code example reuses elements (variables, etc.) defined in earlier examples.
    >
    sort2([2, 1, 3], 'something else');
    Result:
    type error: Argument of type '"something else"' is not assignable to parameter of type '"asc" | "desc"'.Pass Icon
  • We could theoretically have used a boolean above. But seeing 'asc' or 'desc' is more descriptive than true or false.

  • When we have more than two possible values, literal types really shine. For example, suppose that we're writing a database library.

  • >
    type DatabaseType = 'mysql' | 'postgres' | 'oracle';
    let dbType: DatabaseType = 'mysql';
    dbType;
    Result:
    'mysql'Pass Icon
  • >
    type DatabaseType = 'mysql' | 'postgres' | 'oracle';
    let dbType: DatabaseType = 'msaccess';
    dbType;
    Result:
    type error: Type '"msaccess"' is not assignable to type 'DatabaseType'.Pass Icon
  • With this type constraint in place, a user is immediately told if they try to use our library with an unsupported database. It will also tell them if they have a typo in the database name. They don't even have to run the application to see a failure. It can't run at all because it contains type errors.

  • true and false are also literal types. A variable of type true can never be false.

  • >
    let t: true = true;
    t;
    Result:
    truePass Icon
  • >
    let t: true = false;
    t;
    Result:
    type error: Type 'false' is not assignable to type 'true'.Pass Icon
  • Another way to think of a boolean type is as a true | false, which is a broader type than just true. This means that we can't assign a boolean to a variable of type true, since a boolean might sometimes be false.

  • By analogy: we can't assign a number | string to a variable of type number.

  • >
    function aBoolean(): boolean { return true; }
    let t: true = aBoolean();
    t;
    Result:
    type error: Type 'boolean' is not assignable to type 'true'.Pass Icon