Advanced types - Type Casting, index properties, Function overloads, Optional chaining, Nullish Coalescing

  1. Type Casting

    Type conversion tells TS that a value is of a specific type without TS being able to detect it on its own.

    TS cannot detect the type in some cases. For example, in HTML, id is used to obtain the DOM (what is obtained is broad as HTMLElement, not the specific element), and the same is true for data obtained from the backend.

    Two syntaxes for Type Casting (equivalent):

    1. Non-React

      Prepend <type> before the value to specify the type.

      1
      const userInputElement = <HTMLInputElement>document.getElementById("user-input");

    1. React

      Use the as keyword to specify the type.

      1
      const userInputElement = document.getElementById("user-input") as HTMLInputElement;

  2. Non-empty assertion!

    ! means that the preceding expression will never produce null. If the programmer knows that the value will never be null, they can declare it this way. If you are unsure, you can use an if check.

    ! There is also an alternative. The type of the value before ! should be some type | null, so ! is needed. Therefore, if we specify it as some type with as, we can replace !.

    1
    2
    3
    if (userInputElement) {
    (userInputElement as HTMLInputElement).value = "Hi there!";
    }

  3. index properties index type

    Index properties can be used to define dynamic properties in object types. Usually we need to define all possible properties in the object type, but sometimes we don’t know what properties the object will have, or we need to allow users to define arbitrary properties. Index properties can be used at this time.

    Notice:

    1. index property must be of string or numeric type. The index property can be used alone as the only type of property in an object.

    2. The type of the index property must be consistent with the type of other known properties in the object, or be their subtype.

    3. If the object already contains a property, the type of this property must be the same as the type of the index property or its subtype. (This is because the index property is a summary of the types in the object)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    interface User {
    [key: string]: string | number;
    name: string;
    age: number;
    }

    const user: User = {
    name: 'Alice',
    age: 30,
    email: 'alice@example.com',
    phone: 1234567890,
    };

    console.log(user.name); // Alice
    console.log(user.age); // 30
    console.log(user.email); // alice@example.com
    console.log(user.phone); // 1234567890

  4. Function overloads function overload

    Function overloads allow multiple function type signatures to be defined for the same function. Each function type signature defines a set of parameter and return value types. Function overloading will automatically select the correct function type signature to execute the function based on the type and number of parameters passed in.

    Through function overloading, the compiler checks whether the function call conforms to the expected type at compile time, and automatically selects the correct function type signature to execute the code at runtime, thus improving the readability and maintainability of the code.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    function add(a: string, b: string): string;
    function add(a: number, b: number): number;
    function add(a: any, b: any): any {
    return a + b;
    }

    console.log(add('Hello ', 'World')); // Hello World
    console.log(add(2, 3)); // 5

    Notice:

    1. Function overloading must be declared first (written directly above the main function).

    2. The parameter types and return value types in the main function must be compatible with all function type signatures.

    3. The function type signature of function overloading can have any number and any type of parameters, as long as different function type signatures can be distinguished.

    4. Using function overloading, there is no need to write conditional judgment statements in the main function to determine the parameter type. The TypeScript compiler will automatically select the correct function type signature to execute the function based on the parameter type.


  5. Optional chaining

    Optional chaining allows developers to avoid program crashes or exceptions caused by the non-existence of a property or method when accessing a property or method that may not exist (such as obtaining data from the backend, which cannot guarantee data integrity). Using Optional chaining, you can add a question mark ? when accessing a property or method to indicate that the property or method may not exist, thus avoiding exception errors caused by the non-existence of the property or method.

    Note that Optional chaining is only available in TypeScript 3.7 and above.

    1
    2
    3
    4
    // Use the ?. operator when accessing properties that may not exist
    const name = obj?.person?.name;
    // Use the ?. operator when calling methods that may not exist
    const result = obj?.person?.getName();

  6. Nullish Coalescing ??

    Nullish Coalescing (??) is an operator similar to ||.

    The difference between them is that ||’s judgment standard for the previous value is falsy, that is: Boolean value false, 0, -0, '' empty string, null , undefined, NaN.

    ?? The criterion for judging the previous value is null or undefined instead of false.

    1
    2
    3
    const userInput = ""
    const storedData1 = userInput || "DEFAULT" //If userInput is falsy, use the following value.
    const storedData2 = userInput ?? "DEFAULT" //If userInput is null or, use the subsequent value.

Share