Execute Program

TypeScript Basics: Generic Function Types

Welcome to the Generic Function 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 already seen generic functions.

  • >
    function first<T>(elements: Array<T>): T {
    return elements[0];
    }
  • Note: this code example reuses elements (variables, etc.) defined in earlier examples.
    >
    first<boolean>([true, false, true]);
    Result:
    truePass Icon
  • Note: this code example reuses elements (variables, etc.) defined in earlier examples.
    >
    first<string>(['a', 'b', 'c']);
    Result:
    'a'Pass Icon
  • Note: this code example reuses elements (variables, etc.) defined in earlier examples.
    >
    first<number>([true, false, true]);
    Result:
    type error: Type 'boolean' is not assignable to type 'number'.Pass Icon
  • Every function has a type, so generic functions must have types too. Currently, TypeScript is inferring the type of our function automatically. However, we can write its type down if we want to.

  • Note: this code example reuses elements (variables, etc.) defined in earlier examples.
    >
    type First<T> = (elements: Array<T>) => T;
  • Make sure to compare that type to the original first function. The type says: "First is a function type that takes an array of things. It returns one of those things." The "things" part of the type is written as <T>.

  • We can use this type to narrow our first function, just as we've narrowed objects previously. We'll narrow it to a version that only works on strings.

  • Note: this code example reuses elements (variables, etc.) defined in earlier examples.
    >
    const firstString: First<string> = first;
  • Note: this code example reuses elements (variables, etc.) defined in earlier examples.
    >
    firstString(['a', 'b']);
    Result:
    'a'Pass Icon
  • Note: this code example reuses elements (variables, etc.) defined in earlier examples.
    >
    firstString([1, 2]);
    Result:
    type error: Type 'number' is not assignable to type 'string'.Pass Icon
  • When this code executes, the compiled firstString function will be identical to our very first generic version. Narrowing only affects the types.

  • Why would we want to add code that doesn't change the compiled program? For the same reason that we use types in any other situation: to tell the compiler how to reject incorrect programs.

  • Maybe we have a part of the system where we want the first number in an array of numbers. But we also want to make sure that no strings sneak in. Why not tell the type system that it's a First<number>? That way it can keep us honest!