Parameters<Type>
Extracts the argument types of a function type as a tuple, preserving names and optionality.
type Parameters<Type extends (...args: any) => any> = Type extends (...args: infer P) => any ? P : never- Added in TypeScript 3.1
Parameters
| Parameter | Type | Description |
|---|---|---|
$Type | (...args: any) => any | A function type, normally written as `typeof someFunction`. For overloaded functions only the last signature is used. Passing a non-function type fails the constraint and yields `never`. |
Return value
A tuple type of the function's parameter typesA tuple containing one element per parameter, preserving parameter names as tuple labels, optional markers and rest elements. `never` if Type is `never`; `unknown[]` if Type is `any`.
Errors
A type argument that is not a function type errors with "Type 'X' does not satisfy the constraint '(...args: any) => any'" — including the bare `Function` type, which has no call signature to infer from.
Changelog
- PHP 4.0Labelled tuple elements were introduced, so the result now carries the parameter names — `Parameters<(s: string) => void>` displays as `[s: string]` rather than `[string]`.
Parameters uses infer inside a conditional type to capture a function's parameter list as a tuple. It is the type-level half of the rest-and-spread pattern: (...args: Parameters<typeof fn>) => fn(...args) forwards a call with full type safety and no duplication.
When to reach for it
- Wrappers. Memoisation, retry, logging, rate limiting — anything that takes a function and returns one with the same signature.
- Deferred calls. Storing arguments in a queue, replaying them later, or building a fixture table of call/expected pairs.
- Borrowing one parameter.
Parameters<typeof fn>[0]names the first argument's type without exporting it.
What trips people up
You need typeof. Parameters<myFn> is an error — myFn is a value, and type arguments take types. Write Parameters<typeof myFn>.
Overloads collapse to the last signature. Inference picks one, and it picks the last declared overload. If a wrapper must preserve every overload, Parameters is the wrong tool.
Generics are lost. Parameters<typeof identity> on a generic function resolves its type parameters to their constraints (or unknown), so the tuple is wider than the original signature.
Function does not satisfy the constraint, because it declares no call signature.
Example
When to use it
- Write a memoize or retry wrapper whose returned function has the same signature as the original.
- Queue calls by storing their arguments, then replay them with a spread.
- Reference a single argument's type as `Parameters<typeof fn>[0]` without exporting a named interface.
Frequently asked questions
How do I get the argument types of a function in TypeScript?
Use `Parameters<typeof fn>`, which returns a tuple of the parameter types complete with their names, optional markers and rest elements. It was added in TypeScript 3.1.
Why does Parameters<myFunction> not compile?
Because `myFunction` is a value and type arguments require types — you need `Parameters<typeof myFunction>`. The same rule applies to `ReturnType` and `ConstructorParameters`.
Does Parameters work with overloaded functions?
It resolves to the parameters of the last overload signature only, because conditional-type inference picks a single signature. There is no built-in way to extract all overloads.
More examples
A wrapper that keeps the original signature
Prints a `miss:` line, `hello-world`, then a `hit:` line and `hello-world` again. `Parameters<F>` and `ReturnType<F>` together mean `cachedSlugify` has exactly `slugify`'s signature — calling it with one argument, or with the arguments reversed, is a compile error, which a plain `(...args: any[])` wrapper would have allowed.
function slugify(title: string, maxLength: number): string {
return title.toLowerCase().replace(/[^a-z0-9]+/g, "-").slice(0, maxLength);
}
function withCache<F extends (...args: any[]) => any>(fn: F) {
const cache = new Map<string, ReturnType<F>>();
return (...args: Parameters<F>): ReturnType<F> => {
const key = JSON.stringify(args);
if (!cache.has(key)) {
console.log("miss:", key);
cache.set(key, fn(...args));
} else {
console.log("hit: ", key);
}
return cache.get(key) as ReturnType<F>;
};
}
const cachedSlugify = withCache(slugify);
console.log(cachedSlugify("Hello World", 20));
console.log(cachedSlugify("Hello World", 20));Labels, optionality and rest elements survive
Prints `db.internal:5432`, `db.internal:6543`, `db.internal:6543 ssl,pool`, then `localhost`. All three tuples type-check against one `ConnectArgs` because the parameter with a default became an optional tuple element and the rest parameter became a rest element. Indexing the tuple, as in `ConnectArgs[0]`, is the idiomatic way to name a single parameter's type.
function connect(host: string, port = 5432, ...flags: string[]): string {
return `${host}:${port} ${flags.join(",")}`.trim();
}
type ConnectArgs = Parameters<typeof connect>;
// [host: string, port?: number, ...flags: string[]]
const calls: ConnectArgs[] = [
["db.internal"],
["db.internal", 6543],
["db.internal", 6543, "ssl", "pool"],
];
for (const args of calls) {
console.log(connect(...args));
}
type Host = ConnectArgs[0]; // string
const host: Host = "localhost";
console.log(host);
Discussion