September 04, 20202 min readCover by Jehyun Sung

Today I learned - ReturnType<T>


In TypeScript we often deal with functions coming from the untyped third-party libraries or native functions. The details of their implementation might not be clear to us, or their types might differ depending on the environment. So how do we correctly type them in our code? Do we use any to make the TypeScript compiler happy?

What type is timeout?

One of the most common functions used in JavaScript (and thus, TypeScript) is setTimeout:

let timeout;

timeout = setTimeout(() => doSomething(), TIMEOUT_DURATION);

Which type does timeout have? An experienced reader would happily say: number. If you’d ask NodeJS developer they would say: NodeJS.Timeout. Which one is correct? The answer is - it depends.

How do you properly type the function that returns different result types depending on the environment or some other moving conditions? Luckily, TypeScript has a mechanism that solves those dynamic situations.

Meet ReturnType<T>

According to the official TypeScript docs, ReturnType<T> “constructs a type consisting of the return type of function T.

type T0 = ReturnType<() => string>;
//    ^ = type T0 = string
type T1 = ReturnType<(s: string) => void>;
//    ^ = type T1 = void

Ok, so now we know how to extract the return type, but we still need the type of setTimeout to feed it as a generic parameter. Luckily, JavaScript has a neat typeof operator. We can now write the above code as:

let timeout: ReturnType<typeof setTimeout>;

timeout = setTimeout(() => doSomething(), TIMEOUT_DURATION);

TypeScript compiler is now happy and our code is still protected by the correct type.

Did you like the post? Share it on Twitter , LinkedIn or Facebook .
Did you find it helpful? Leaving a small tip helps.

Written by Miroslav Jonas, a software developer focusing on the front-end of things.
He lives and works in Vienna, Austria.