Beginner's TypeScript Tutorial (18 exercises)
solution

Specify the Type for an Async Function

Here's the correct syntax for typing these functions:

const createThenGetUser = async (
  createUser: () => Promise<string>,
  getUser: (id: string) => Promise<User>,
): Promise<User> => {
  const userId: string = await createUser();

  const user = await getUser(userId);

  return user;
};

Same as before, these can be extracted out into their own types as well:

type GetUser = (id: string) => Promise<User>;

What this is saying is that we have an id which is a string, and the function will return a Promise containing a User.

If we had GetUser only returning the User without the Promise, we won't be able to call it as an async function in the test due to errors.

Wrapping function return types with Promises is really useful when working with real world processes like fetching from databases.

Transcript

The correct way to type these functions is using this syntax here. Same as we had before, we can extract these out into a type if we want, type getUser equals this. Then we say getUser inside here. What this is saying is we have our ID, which is a string here. Then, we're saying we're returning a promise containing a user.

If we don't do this, then it's going to be a little bit funky here because type Promise is missing the following properties. We can't do an async function here. Whereas, if we did this instead, then it would be happy. If we were using real fetches to a database using something like Prisma or something similar, then we would need to wrap them in promises. Having these in promises is really, really useful.

What we can do is say this promise string here, if we wanted to, we could make this promise number. Then ID would error here because it would be inferred as number. You get getUser number, type user is not assignable to type string. You get the idea. You can manipulate these pretty well by using this promise syntax to indicate the return type of async functions.