Execute Program

TypeScript Basics: Function Types

Welcome to the 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 seen function definitions with types. But what if we want to put a function in a variable? The variable will need a type that says "I hold a function."

  • A function type looks like (n: number) => number. In English, "a function that takes a number and returns a number."

  • >
    function five(): number {
    return 5;
    }

    /* This is the type of the function itself. */
    type TakesNothingReturnsNumber = () => number;

    const myFive: TakesNothingReturnsNumber = five;
    myFive();
    Result:
    5Pass Icon
  • Here's an add1 function, followed by two examples that apply different static types to it. (One of them will cause an error; you can write type error to indicate that kind of error.)

  • >
    function add1(n: number): number {
    return n + 1;
    }
  • Note: this code example reuses elements (variables, etc.) defined in earlier examples.
    >
    type TakesNumberReturnsNumber = (n: number) => number;
    const myAdd1: TakesNumberReturnsNumber = add1;
    myAdd1(3);
    Result:
    4Pass Icon
  • Note: this code example reuses elements (variables, etc.) defined in earlier examples.
    >
    type TakesNumberReturnsString = (n: number) => string;
    const myAdd1: TakesNumberReturnsString = add1;
    myAdd1(3);
    Result:
    type error: Type '(n: number) => number' is not assignable to type 'TakesNumberReturnsString'.
      Type 'number' is not assignable to type 'string'.Pass Icon
  • Look closely at the type error above. The function add1 was fine: its type is (n: number) => number. The problem occurred when we tried to assign that function to a variable of type (n: number) => string

  • The second line of the type error explains exactly why the functions aren't compatible. It's because their return types are different. The function add1 returns a number but TakesNumberReturnsString returns a string.

  • Type errors often contain this kind of extra explanation telling us why the error happened. They're not perfect, but they're usually helpful.

  • When defining a variable to hold a function, we can specify its type inline.

  • >
    function add1(n: number): number {
    return n + 1;
    }
    const myAdd1: (n: number) => number = add1;
    myAdd1(3);
    Result:
    4Pass Icon
  • >
    function double(n: number): number {
    return 2 * n;
    }
    const myDouble: (n: number) => string = double;
    myDouble(3);
    Result:
    type error: Type '(n: number) => number' is not assignable to type '(n: number) => string'.
      Type 'number' is not assignable to type 'string'.Pass Icon
  • This type error is different from the last one. Last time, the function type had a name, TakesNumberReturnsNumber. This time, it has no name, so the error message contains the full type.

  • In a function definition, we give the arguments names. However, these names aren't part of the type. Only their position matters. We might name an argument s in a function type, but text when defining the function. That's fine and the code will still type check.

  • >
    function downcase(text: string): string {
    return text.toLowerCase();
    }
    type DowncaseFunction = (s: string) => string;
    const myDowncase: DowncaseFunction = downcase;
    myDowncase('HELLO');
    Result:
    'hello'Pass Icon
  • A final note about syntax. TypeScript and JavaScript have two different function syntaxes. There's the older syntax with the function keyword, like function myFunction(x). Then there's the newer (x) => ... syntax, often called "arrow functions". When defining a function with an explicit function type, we can only use the newer arrow function syntax:

  • >
    const numberToString: (s: number) => string = (
    // This is the arrow function that we're assigning to `numberToString`.
    (s) => {
    return s.toString();
    }
    );
    numberToString(5);
    Result:
  • This is a limitation of the TypeScript syntax, not the type system. The TypeScript syntax simply doesn't support old-style functions with explicit function types.