ConstructorParameters
是 TypeScript 中的一个工具类型(utility type),它用于获取构造函数参数的类型。这个工具类型可以用来提取类构造函数的所有参数类型的元组。
用法
ConstructorParameters
的基本语法如下:
type ConstructorParameters<T> = T extends new (...args: infer P) => any ? P : never;
T
是一个构造函数类型。infer P
用于推断构造函数的参数类型,并将它们存储在P
中。- 如果
T
不是一个构造函数,那么结果将是never
。
示例
假设你有一个类 Person
,它的构造函数接受两个参数:name
和 age
。
class Person {
constructor(public name: string, public age: number) {}
}
你可以使用 ConstructorParameters
来提取 Person
类构造函数的参数类型:
type PersonParams = ConstructorParameters<typeof Person>;
// PersonParams 的类型是 [string, number]
具体应用场景
1. 创建工厂函数
假设你想创建一个工厂函数来生成 Person
实例,但你希望确保工厂函数的参数与 Person
构造函数的参数一致。
function createPerson(...args: ConstructorParameters<typeof Person>) {
return new Person(...args);
}
const person = createPerson("Alice", 30); // 正确
// const person2 = createPerson("Bob"); // 编译错误,缺少参数
2. 泛型工厂函数
如果你有多个类,并且希望为这些类创建通用的工厂函数,你可以使用泛型和 ConstructorParameters
。
class Employee {
constructor(public name: string, public department: string) {}
}
function createInstance<T>(ctor: new (...args: any[]) => T, ...args: ConstructorParameters<typeof ctor>): T {
return new ctor(...args);
}
const employee = createInstance(Employee, "John Doe", "HR");
const person = createInstance(Person, "Jane Doe", 25);
console.log(employee); // Employee { name: 'John Doe', department: 'HR' }
console.log(person); // Person { name: 'Jane Doe', age: 25 }
在这个例子中,createInstance
函数接受一个构造函数 ctor
和任意数量的参数 args
。args
的类型由 ConstructorParameters<typeof ctor>
确定,这样可以确保传入的参数与构造函数的参数类型匹配。
3. 参数类型检查
你还可以使用 ConstructorParameters
来进行参数类型检查,确保传递给某个函数或方法的参数与预期的构造函数参数类型一致。
function checkPersonParams(...params: ConstructorParameters<typeof Person>) {
if (typeof params[0] !== 'string') {
throw new Error('First parameter must be a string');
}
if (typeof params[1] !== 'number') {
throw new Error('Second parameter must be a number');
}
}
try {
checkPersonParams("Alice", 30); // 通过
checkPersonParams(42, "Alice"); // 抛出错误
} catch (error) {
console.error(error.message);
}
总结
ConstructorParameters
是一个非常有用的工具类型,可以帮助你在 TypeScript 中提取和使用构造函数的参数类型。这使得代码更加类型安全,减少了手动维护类型定义的工作量。通过结合泛型和其他 TypeScript 特性,你可以编写出更加灵活和健壮的代码。