Execute Program

Everyday TypeScript: Promises

Welcome to the Promises lesson!

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

  • Promises are the core concept in modern JavaScript concurrency. If you've never used them before, we recommend pausing your work in this course, and switching to our JavaScript Concurrency course. That course will give you a good foundation for understanding this lesson and a few that follow. Promises are important in all JavaScript and TypeScript programming, so it's important to understand them!

  • TypeScript needs to statically type promises, just like it does for other code. Although promises and concurrency are tricky topics, the TypeScript types for them are surprisingly straightforward.

  • All promises have the type Promise<T>, where T is the type of the value inside the promise. For example, a fulfilled promise that contains a number will be a Promise<number>.

  • However, we need to mention one complication that's specific to Execute Program. When Execute Program's code examples return promises, we need a way for you to type them in as an answer. For other JavaScript values like objects and arrays, that's easy: you type in the object or array, like {name: 'Amir'} or [1, 2, 3]. But JavaScript doesn't have a "literal syntax" like this for promises; there's no way to directly write out a promise value.

  • Our solution is to make up our own representation of promises. When a code example returns a fulfilled promise, it will look like {fulfilled: someValue}.

  • (Note that some of the example below cause type errors.)

  • >
    Promise.resolve(5);
    Asynchronous Icon Async Result:
  • >
    Promise.resolve(5).then(n => n * 2);
    Asynchronous Icon Async Result:
    {fulfilled: 10}Pass Icon
  • >
    const promise: Promise<number> = Promise.resolve(100);
    promise;
    Asynchronous Icon Async Result:
    {fulfilled: 100}Pass Icon
  • >
    const promise: Promise<string> = Promise.resolve(100);
    promise;
    Asynchronous Icon Async Result:
    type error: Type 'Promise<number>' is not assignable to type 'Promise<string>'.
      Type 'number' is not assignable to type 'string'.Pass Icon
  • >
    const promise: number = Promise.resolve(100);
    promise;
    Asynchronous Icon Async Result:
    type error: Type 'Promise<number>' is not assignable to type 'number'.Pass Icon
  • TypeScript correctly handles situations where a then callback returns a different type from what it received. For example, we might have a Promise<number> chained with a then returning a string. The .then(...) call will return a Promise<string>.

  • >
    const promise: Promise<number> = Promise.resolve(100);
    promise;
    Asynchronous Icon Async Result:
    {fulfilled: 100}Pass Icon
  • >
    const promise: Promise<string> = Promise.resolve(100)
    .then(n => n.toString());
    promise;
    Asynchronous Icon Async Result:
    {fulfilled: '100'}Pass Icon
  • >
    const promise: Promise<number> = Promise.resolve(100)
    .then(n => n.toString());
    promise;
    Asynchronous Icon Async Result:
    type error: Type 'Promise<string | number>' is not assignable to type 'Promise<number>'.
      Type 'string | number' is not assignable to type 'number'.
        Type 'string' is not assignable to type 'number'.Pass Icon
  • Here's a code problem:

    The double function below doubles numbers stored in promises. Its return type is currently wrong: it says that it returns a number, but it really returns a promise. This is a common mistake when using promises in TypeScript. It's easy to forget to give functions a Promise return type.

    Modify the function's return type to match reality: the function returns a promise that contains a number. (You won't need to change any part of the function other than the return type.)

    function double(numberPromise: Promise<number>): Promise<number> {
    return numberPromise.then(n => n * 2);
    }
    double(Promise.resolve(2)).then(n1 => {
    return double(Promise.resolve(3)).then(n2 => {
    return [n1, n2];
    });
    });
    Asynchronous Icon Async Result:
    Goal:
    {fulfilled: [4, 6]}
    Yours:
    {fulfilled: [4, 6]}Pass Icon