Patrick Desjardins Blog
Patrick Desjardins picture from a conference

TypeScript Awaited Type

Posted on: 2022-01-26

Before TypeScript version 4.5, there was a unexpected type conversion happening with Promise. The current code is working prior to version 4.5.

async function computationLogic<T>(arg: Promise<T>): Promise<T[]> {
  return [await arg];
}

class Observer<T> {
  private value: T | undefined;
  public constructor(t: T | undefined = undefined) {
    this.value = t;
  }
  async getValue() {
    return this.value;
  }
  async compute() {
    return computationLogic(this.getValue());
  }
}

(async () => {
  const p = new Observer<Promise<string>>();
  const m = await p.compute(); //  Promise<string>[] instead of string[]
})();

The code compile and but the line 20, the last highlighted line, return for the variable m a type of Promise<string>[] which is not true. Because at line 2, we are use await we are returning an array of awaited type. The awaited type of a Promise is the generic type. Thus, in that case T which is string.

The next code contains the use of the new Awaited<> that specify to TypeScript that we are returning the type resolved.

async function computationLogic<T>(arg: Promise<T>): Promise<Awaited<T>[]> {
  return [await arg];
}

class Observer<T> {
  private value: T | undefined;
  public constructor(t: T | undefined = undefined) {
    this.value = t;
  }
  async getValue() {
    return this.value;
  }
  async compute() {
    return computationLogic(this.getValue());
  }
}

(async () => {
  const p = new Observer<Promise<string>>();
  const m = await p.compute(); //  Promise<string>[] instead of string[]
})();

The type of m is not string[] instead of a promise of string[]. As expected at runtime! While researching the new awaited feature I found very limited example or usage. All of them, as I am writing this blog post are revolving around an array of generic type. I suspect that this will be useful to have an accurate return type when using promises and arrays. For example, with Promise.all()