ReturnType Utility Type in TypeScript

ReturnType<T> extracts the return type of a function type. Use it to capture a function's output type without duplicating the type annotation.

5 min read

The TypeScript ReturnType utility type extracts the return type from a function type. Instead of writing the return type twice, once in the function and once where you consume the result, you let ReturnType derive it for you.

This is most useful when you have a function whose return type is complex or may change. Rather than maintaining a separate type annotation that can drift out of sync, you point ReturnType at the function and the compiler keeps the derived type accurate automatically.

typescripttypescript
function createUser(name: string, age: number) {
  return { id: Math.random(), name, age, createdAt: new Date() };
}
 
type User = ReturnType&lt;typeof createUser&gt;;

The type User resolves to { id: number; name: string; age: number; createdAt: Date }. If createUser changes to return an extra field like isActive, the User type updates automatically. You never need to change the derived type by hand.

How ReturnType works

ReturnType takes a function type and produces whatever type that function returns. It is a single-argument utility: you pass it a function type, and it gives you back the return type.

typescripttypescript
type FromArrow = ReturnType<() => string>;
type FromDeclared = ReturnType<() => number>;
type FromMethod = ReturnType<Array&lt;string&gt;["pop"]>;

FromArrow resolves to string. FromDeclared resolves to number. FromMethod resolves to string | undefined, because that is what Array.pop returns.

ReturnType only accepts function types. If you pass a non-function type like string or number, the compiler reports an error because those types do not satisfy the required function constraint.

ReturnType with typeof

The most common pattern pairs ReturnType with the typeof type operator. typeof captures the type of a named function, and ReturnType extracts what that function produces.

typescripttypescript
function fetchUser(id: number) {
  return { id, name: "Ada", role: "admin" as const };
}
 
type FetchedUser = ReturnType&lt;typeof fetchUser&gt;;

FetchedUser resolves to { id: number; name: string; role: "admin" }. The as const on role preserved the literal type "admin" instead of widening to string. ReturnType faithfully captures every detail of the return value.

This pattern shines when the return type is too complex or tedious to write by hand. A function that builds a deeply nested configuration object or transforms API data can have a long, detailed return type. ReturnType captures it in one line.

Practical use: typing test fixtures

A common use case is in test files. You have a factory function that builds test data. Instead of maintaining a separate TestUser type, derive it from the factory:

typescripttypescript
function makeUser(overrides?: Partial<{ name: string; age: number }>) {
  return { id: 1, name: "Test", age: 0, ...overrides };
}
 
type TestUser = ReturnType&lt;typeof makeUser&gt;;
 
function assertIsUser(value: unknown): asserts value is TestUser {
  if (typeof value !== "object" || value === null) {
    throw new Error("Not a user");
  }
}

If makeUser gains a new default property later, TestUser includes it automatically. The assertion function stays accurate without manual updates.

ReturnType and async functions

For async functions, ReturnType gives you Promise&lt;T&gt;, not the resolved value T. To get the value inside the promise, use the Awaited utility type, which was introduced in TypeScript 4.5:

typescripttypescript
async function loadConfig() {
  return { theme: "dark", locale: "en" };
}
 
type Config = Awaited<ReturnType&lt;typeof loadConfig&gt;>;

Config resolves to { theme: string; locale: string }. Without Awaited, you would get a Promise wrapping that same shape, which is the function's actual return type but not the shape you want to work with after awaiting.

ReturnType with overloaded functions

Overloaded functions have multiple signatures. ReturnType extracts the return type of the last overload signature, not the implementation signature.

typescripttypescript
function format(value: string): string;
function format(value: number): string;
function format(value: string | number): string {
  return String(value);
}
 
type FormatReturn = ReturnType&lt;typeof format&gt;;

FormatReturn is string. Since both overloads return string, the last one gives the same result.

If overloads return different types, you may get an unexpected result, since ReturnType only sees the final signature. In that case, declare a separate type alias for the signature you want to extract. For the complementary utility that extracts parameter types instead, see Parameters utility type in TypeScript.

Common mistakes

Using ReturnType on the function directly instead of typeof. ReturnType&lt;createUser&gt; does not work because createUser is a value, not a type. Always use ReturnType&lt;typeof createUser&gt; to first get the function's type, then extract its return type. For more on typeof, see typeof type operator in TypeScript.

Forgetting that async functions return promises. ReturnType on an async function gives you a Promise wrapping the resolved value, not the value itself. If you need the resolved type, wrap it with Awaited.

Overusing ReturnType for simple types. If a function returns string, writing a ReturnType expression is more verbose than just writing the plain string type directly. Use ReturnType when the return type is complex, likely to change, or tedious to write by hand.

Rune AI

Rune AI

Key Insights

  • ReturnType<T> extracts the return type from a function type.
  • Combine it with typeof to capture the return type of a specific function.
  • It works with arrow functions, declared functions, and methods.
  • For async functions, wrap with Awaited to get the resolved value type.
  • Like all utility types, ReturnType exists only at compile time.
RunePowered by Rune AI

Frequently Asked Questions

Can ReturnType extract the return type of an async function?

Yes. ReturnType on an async function gives you Promise&lt;T&gt;, where T is the value you await. Use the Awaited utility type to unwrap it: Awaited&lt;ReturnType&lt;typeof myAsyncFn&gt;&gt;.

What happens if I use ReturnType on a non-function type?

TypeScript reports an error: Type 'string' does not satisfy the constraint '(...args: any) => any'. ReturnType only accepts function types.

How does ReturnType behave with overloaded functions?

It extracts the return type of the last overload signature. If you need a specific overload, you may need to declare the function type with only that signature.

Conclusion

ReturnType is the cleanest way to capture a function's return type without writing it twice. Use typeof to get the function type, then ReturnType to extract what it produces. It keeps derived types in sync with the source and eliminates a common source of drift.