ReturnType<T> and Parameters<T> are utility types in TypeScript that allow you to automatically infer the return type of a function (ReturnType) or an array of its parameter types (Parameters).
This is especially convenient for maintaining type consistency across different parts of the application and for implementing generic wrappers.
Example usage:
function fn(a: number, b: string): boolean { return b.length > a; } type FnReturn = ReturnType<typeof fn>; // boolean type FnParams = Parameters<typeof fn>; // [number, string]
Nuances with function overloading: When overloading functions, ReturnType determines the last variant of the signature, while Parameters captures all possible overloads:
function overloaded(x: number): number; function overloaded(x: string): string; function overloaded(x: any): any { return x; } type OverRet = ReturnType<typeof overloaded>; // any type OverParams = Parameters<typeof overloaded>; // [any]
Thus, the typing of utility types does not always "see" all overloads, making static typing less predictable.
Can you use ReturnType and Parameters to get the types of all possible overloads of a custom function, defining each overload separately?
Answer:
No. The utility types ReturnType and Parameters only analyze the "merged" signature of the function — as it is described for implementation. They do not allow you to obtain the types of each individual overload — only the final implemented signature.
Example:
type P = Parameters<typeof overloaded>; // [any], not [number], [string]
Story
Developers wrote a wrapper aroundMethod using ReturnType<T> to type the return value. However, the wrapper function was applied to an overloaded function. Result: types were too general (any), and when errors occurred, the compiler did not signal a mismatch in return values. A bug was discovered late when working with booleans instead of strings.
Story
In an attempt to infer parameters for multiple API functions using Parameters<T>, the developer did not account for the method overloads. This led to a problem with "incorrect" types, where [string, number] was expected instead of [any]. Unit tests did not catch this error due to mocking through implementation, and real API users encountered bugs in production.
Story
While migrating a large codebase from JavaScript to TypeScript, developers typed everything using ReturnType. Later, they realized that the implementation differed significantly from the declaration of overloads. As a result, scenarios with incorrect arguments caused unexpected runtime exceptions (e.g., TypeError: x is undefined).