Introduction

Duplicating function parameter types by hand is fragile — change the original function signature and you have to hunt down every copy. Parameters<Type> extracts function parameter types as a tuple so you can reuse them automatically. Here is how it works and where it’s most useful.

What is Parameters<Type>?

Parameters<Type> is a TypeScript utility type that extracts the parameter types of a function type and returns them as a tuple. It is useful when you want to reuse the parameter types of a function without duplicating type declarations.

Syntax

js
type Parameters<T extends (...args: any) => any> = T extends (...args: infer P) => any ? P : never;

The Parameters<Type> utility works by using TypeScript’s conditional types and infer keyword to capture the parameter types from a given function.

Example

js
function greet(name: string, age: number): string {
  return `Hello, my name is ${name} and I am ${age} years old.`;
}

// Using Parameters<Type> to extract the parameter types
type GreetParams = Parameters<typeof greet>; // [string, number]

const greetArgs: GreetParams = ['Alice', 30];
console.log(greet(...greetArgs)); // Output: Hello, my name is Alice and I am 30 years old.

In this example, the Parameters<typeof greet> type extracts the function’s parameters, which are [string, number]. This allows you to reuse the parameters without manually specifying them again.

Practical Use Cases for Parameters<Type>

1. Wrapping Functions

When you need to create a wrapper function that passes the same parameters as an existing function, Parameters<Type> can ensure type safety.

js
function logFunctionCall(fn: (...args: any[]) => any) {
  return (...args: Parameters<typeof fn>) => {
    console.log(`Function called with arguments:`, args);
    return fn(...args);
  };
}

const wrappedGreet = logFunctionCall(greet);
wrappedGreet('Rebeca', 45); // Logs: Function called with arguments: ["Rebeca", 25]

Here, the logFunctionCall function uses Parameters<Type> to match the parameter types of the function it wraps, ensuring that any function passed to it maintains the correct argument structure.

2. React Event Handlers

In React, using Parameters<Type> is helpful when defining event handlers with the correct type signature.

js
import React from 'react';

type ButtonClickHandler = Parameters<React.MouseEventHandler<HTMLButtonElement>>;

const handleClick: React.MouseEventHandler<HTMLButtonElement> = (event) => {
  console.log('Button clicked:', event);
};

const Button = () => <button onClick={handleClick}>Click Me</button>;

Using Parameters ensures that the handleClick function has the exact type signature required by React’s event handler.

Besides Parameters<Type>, TypeScript provides several other utility types to work with function types and object types.

1. ReturnType<Type>

ReturnType<Type> extracts the return type of a function.

js
function add(x: number, y: number): number {
  return x + y;
}

type AddReturnType = ReturnType<typeof add>; // number

2. ConstructorParameters<Type>

ConstructorParameters<Type> works similarly to Parameters, but for constructor functions.

js
class Person {
  constructor(public name: string, public age: number) {}
}

type PersonConstructorParams = ConstructorParameters<typeof Person>;  // [string, number]

3. InstanceType<Type>

InstanceType<Type> extracts the type of an instance created by a constructor.

js
type PersonInstance = InstanceType<typeof Person>; // Person

Benefits of Using Utility Types

  • Code Reusability: Utility types allow you to reuse existing type definitions, making your code cleaner and reducing duplication.
  • Type Safety: By deriving types from existing functions or objects, you ensure consistency across your codebase.
  • Flexibility: Utility types offer a more dynamic and adaptable approach to working with types in TypeScript.

Conclusion

Parameters<Type> eliminates a common source of type drift — hardcoded parameter lists that fall out of sync with the functions they mirror. Combine it with ReturnType and ConstructorParameters and most wrapper / decorator patterns become type-safe without manual duplication.