Question
Given this TypeScript function:
function test(): number {
return 42;
}
Using typeof test produces the function type () => number:
type T = typeof test;
How can you obtain only the function's return type, so that the resulting type is number rather than () => number?
Short Answer
You can extract a function's return type in TypeScript with the built-in ReturnType<T> utility type. Combine it with typeof when starting from a named function:
type Result = ReturnType<typeof test>; // number
By the end, you will know the difference between a function type and its result type, and how to reuse return types safely in real code.
Concept
typeof and ReturnType answer two different questions in TypeScript.
typeof testasks: What is the type of the function value namedtest?ReturnType<typeof test>asks: What type does that function produce when called?
For example:
function test(): number {
return 42;
}
type FunctionType = typeof test; // () => number
type TestResult = ReturnType<typeof test>; // number
ReturnType<T> is a built-in utility type. It accepts a function type and extracts the type after the function's arrow, such as number in () => number.
This matters because return types are often shared. For example, a helper may create an object that another function, state variable, or API handler needs to use. Deriving the type avoids manually writing the same object shape in multiple places.
Mental Model
Think of a function as a vending machine.
typeof testdescribes the whole machine: it takes no input and dispenses a number. Its type is() => number.ReturnType<typeof test>describes only the item that comes out: anumber.
typeof gives you the machine's instruction label. ReturnType reads that label and picks out the output.
Syntax and Examples
Use ReturnType with a function type.
type ReturnType<T extends (...args: any[]) => any> = /* built in */;
In normal code, you do not define it yourself. Use TypeScript's built-in version:
function test(): number {
return 42;
}
type T = ReturnType<typeof test>;
// T is number
For a function type written directly, pass that type to ReturnType:
type Formatter = (value: string) => string;
type FormattedValue = ReturnType<Formatter>;
// FormattedValue is string
It also works well with functions that return objects:
function createUser(name: string) {
return {
id: crypto.randomUUID(),
name,
active: true,
};
}
type User = ReturnType<typeof createUser>;
// { id: string; name: string; active: boolean }
Step by Step Execution
Consider this example:
function calculateTotal(price: number, quantity: number): number {
return price * quantity;
}
type Calculator = typeof calculateTotal;
type Total = ReturnType<typeof calculateTotal>;
TypeScript evaluates the type aliases as follows:
-
calculateTotalis a function that accepts twonumberarguments. -
It returns a
number. -
typeof calculateTotalbecomes the full function type:(price: number, quantity: number) => number -
ReturnType<typeof calculateTotal>examines that function type. -
It extracts the output portion after
=>. -
Therefore,
Totalisnumber.
ReturnType affects only TypeScript's compile-time type checking. It does not call the function or change JavaScript generated at runtime.
Real World Use Cases
Common uses include:
-
Factory functions: Derive the type of an object created by a function.
function createConfig() { return { retries: 3, logging: true }; } type Config = ReturnType<typeof createConfig>; -
API client helpers: Reuse the result type from a request function.
async function fetchProducts() { return [{ id: 1, name: "Keyboard" }]; } type Products = Awaited<ReturnType<typeof fetchProducts>>; -
State initialization: Ensure state matches the value produced by a setup function.
function initialFilters() { return { query: "", page: 1 }; } type Filters = ReturnType<typeof initialFilters>; -
Library wrappers: Keep wrapper code synchronized when an underlying function's result changes.
Real Codebase Usage
In production code, ReturnType is most useful when it eliminates duplicated type declarations.
Derive a factory result
function createSession(userId: string) {
return {
userId,
createdAt: new Date(),
token: crypto.randomUUID(),
};
}
type Session = ReturnType<typeof createSession>;
function saveSession(session: Session): void {
// Save the session.
}
If createSession later adds a property, Session updates automatically.
Combine it with Awaited for async code
An async function returns a Promise, so ReturnType includes that promise:
async function getAccount(id: string) {
return { id, plan: "pro" as const };
}
type AccountPromise = ReturnType<typeof getAccount>;
// Promise<{ id: string; plan: "pro" }>
type Account = Awaited<ReturnType<typeof getAccount>>;
// { id: string; plan: "pro" }
Use it for callbacks
const toDisplayName = (first: string, last: string) => `${first} ${last}`;
type DisplayName = ReturnType<typeof toDisplayName>;
// string
Prefer explicit exported interfaces or type aliases when they make a public API easier to understand. Use ReturnType when the type should intentionally follow a function implementation.
Common Mistakes
Using typeof alone
This gives the function type, not its output type:
function test(): number {
return 42;
}
type T = typeof test; // () => number
Fix it by wrapping the function type in ReturnType:
type T = ReturnType<typeof test>; // number
Calling the function in a type position
This is not valid TypeScript type syntax:
// type T = typeof test(); // Invalid
Use ReturnType<typeof test> instead. Types describe code without executing it.
Forgetting that async functions return promises
async function loadCount(): Promise<number> {
return 5;
}
type T = ReturnType<typeof loadCount>; // Promise<number>
If you need the resolved value, unwrap it:
type Count = Awaited<ReturnType<typeof loadCount>>; // number
Passing a non-function type
ReturnType only accepts function types.
type Broken = ReturnType<string>; // Error: string is not a function type
Expecting ReturnType to preserve every overload result
For an overloaded function, TypeScript generally infers from the last overload signature. If each overload's result must be represented precisely, define and use a more specific function type instead.
Comparisons
| Tool or syntax | What it describes | Example result |
|---|---|---|
typeof test | The function value's complete type | () => number |
ReturnType<typeof test> | The function's output type | number |
Parameters<typeof test> | A tuple of input parameter types | [] |
Awaited<ReturnType<typeof asyncFn>> | The resolved output of an async function | number instead of Promise<number> |
| Explicit return annotation | Documents or constrains a function's output | function test(): number |
ReturnType is best when a function already exists and another type should follow its result. An explicit return annotation is best when you want to state the function's intended contract directly.
Cheat Sheet
function test(): number {
return 42;
}
// Full function signature
type FunctionType = typeof test;
// () => number
// Return value type
type Result = ReturnType<typeof test>;
// number
// Function type written directly
type Result = ReturnType<(id: string) => boolean>;
// boolean
// Async function: promise type
type PromiseResult = ReturnType<typeof fetchData>;
// Promise<Data>
// Async function: resolved type
type Data = Awaited<ReturnType<typeof fetchData>>;
Rules:
- Pass a function type to
ReturnType. - Use
typeof functionNameto obtain a named function's type. ReturnTypeis compile-time only; it does not execute code.- Use
Parameters<typeof fn>to extract inputs instead of outputs.
FAQ
How do I get a function's return type in TypeScript?
Use ReturnType with the function's type:
type Result = ReturnType<typeof test>;
Why does typeof test return () => number instead of number?
test refers to the function itself, not the value returned after calling it. Therefore, typeof test describes its callable signature.
Does ReturnType call the function?
No. It is a TypeScript utility type used only during type checking. It has no runtime behavior.
How do I get the return type of an async function?
ReturnType<typeof fn> gives the promise type. Use Awaited to get the resolved value type:
type Value = Awaited<ReturnType<typeof fn>>;
Can I use ReturnType with arrow functions?
Yes.
const isReady = () => true;
type Ready = ReturnType<typeof isReady>; // boolean
Can I get a function's parameter types too?
Yes. Use the built-in Parameters<T> utility type:
type Args = Parameters<typeof test>; // []
What happens with overloaded functions?
ReturnType usually uses the last overload signature. For precise behavior, create a specific function type for the overload case you need.
Mini Project
Description
Build a small order-summary module. A factory function creates an order summary object, and other functions reuse its derived return type. This demonstrates how ReturnType keeps related code synchronized as the factory changes.
Goal
Create and use a ReturnType<typeof createOrderSummary> alias instead of manually repeating the order summary object type.
Requirements
Create a createOrderSummary function that accepts an item name, unit price, and quantity.
Return an object containing the item name, quantity, subtotal, tax, and total.
Create an OrderSummary type using ReturnType<typeof createOrderSummary>.
Write a printReceipt function that accepts an OrderSummary.
Create one summary and print its receipt.
Keep learning
Related questions
@Directive vs @Component in Angular: Differences, Use Cases, and When to Use Each
Learn the difference between @Directive and @Component in Angular, including use cases, examples, and when to choose each.
Accessing Input Value from EventTarget in TypeScript
Learn why EventTarget has no value property in TypeScript and safely read values from HTML input events in Angular applications.
Angular (change) vs (ngModelChange): What’s the Difference?
Learn the difference between Angular (change) and (ngModelChange), when each fires, and which one to use in forms and inputs.