Background
With the development of TypeScript, there arose a need to automatically extract the return type from a function, especially for large projects with many interconnected functions. For this purpose, the utility type ReturnType<T> was introduced, which appeared in the standard library starting from TypeScript version 2.8.
Problem
In large and complex projects, it can be challenging to keep types up to date — if you manually specify the return type of each function and then change the signatures, it’s easy to create mismatches when the signatures and implementations do not align. Additionally, if a function returns a complex structure, synchronizing the return type description manually across all usage points can be cumbersome.
Solution
The utility type ReturnType<T> automatically extracts the return type of functions and can be used to type the result of a function call anywhere in the code. This reduces the amount of manual type infrastructure maintenance and minimizes errors associated with discrepancies between the described and actual return type.
Code example:
function createUser(name: string, age: number) { return { name, age, created: new Date() }; } type User = ReturnType<typeof createUser>; // User: { name: string; age: number; created: Date; }
Key features:
Can ReturnType be used with class methods?
Yes, but it’s important to keep the context in mind: if the method is a property of an object with a function, use ReturnType<obj['method']>.
Code example:
class MyClass { foo(x: number) { return x * 2; } } type FooReturn = ReturnType<MyClass['foo']>; // Type error! // Needs to be: type FooReturn = ReturnType<(x: number) => number>; // number // Or extract the method as a function: const obj = new MyClass(); type FooReturn2 = ReturnType<typeof obj.foo>;
What will ReturnType return for functions with void/never?
For a function with a declared type of void, ReturnType will return void. For never — it will return never.
Code example:
function doNothing(): void {} type Result = ReturnType<typeof doNothing>; // void
Does ReturnType work with function overloads?
No, ReturnType extracts the return type of the "implementation" itself, not all overloads. If there are multiple overloads, it takes the described type of the implementation.
Code example:
function func(x: number): number; function func(x: string): string; function func(x: any): any { return x } type RT = ReturnType<typeof func>; // any
In a project, a manual type is declared for the return object of a function. The function changes — the type is not updated, and calls fail at runtime.
Pros:
Cons:
They switch to ReturnType everywhere they use the value returned by a function. In the case of changes, the type is always up to date.
Pros:
Cons: