TypeScript限制函数参数为特定类类型,禁止子类传入
限制TypeScript函数参数仅接受“纯”A类型实例
问题场景
我定义了如下TypeScript代码,其中函数foo接受类型为A的参数:
export function foo<T extends A>(arg: A) { console.log(arg.propA); // do something with arg return arg as unknown as A & B & T; } class A { propA: string; constructor() { this.propA = "A"; } } class B extends A { propB: string; constructor() { super(); this.propB = "B"; } } class C { propC: string; constructor() { this.propC = "C"; } }
在调用foo时,我希望第二个调用能触发静态TypeScript错误:
const processedA = foo(new A()); // 正常,符合预期 foo(processedA); // 当前无错误,但需要触发错误 foo(new C()); // 已按预期报错,符合要求
我的思路是判断参数是否包含A定义之外的额外属性,但不知道如何实现。
解决方案
可以通过定义精确类型约束来实现这个需求,确保传入foo的参数类型只能是严格的A,不能包含任何额外属性或被断言为包含额外属性的类型。
修改后的代码
// 定义精确类型检查工具:确保U的属性完全匹配T,无额外键 type Exact<T, U> = U extends T ? Exclude<keyof U, keyof T> extends never ? U : never : never; export function foo<T extends A>(arg: Exact<A, T>) { console.log(arg.propA); // do something with arg return arg as unknown as A & B & T; } class A { propA: string; constructor() { this.propA = "A"; } } class B extends A { propB: string; constructor() { super(); this.propB = "B"; } } class C { propC: string; constructor() { this.propC = "C"; } }
效果验证
const processedA = foo(new A()); // 正常,符合预期 foo(processedA); // 触发TypeScript错误:类型"A & B & A"的参数不能赋给类型"never"的参数 foo(new C()); // 触发TypeScript错误:类型"C"的参数不能赋给类型"never"的参数
原理说明
Exact<T, U>类型会先检查U是否继承自T,再判断U是否包含T之外的额外属性:- 如果
U不是T的子类型,直接返回never,参数类型不匹配报错; - 如果
U是T的子类型,但包含T之外的键,同样返回never,触发错误; - 只有当
U的属性完全和T一致时,才返回U,允许正常调用。
- 如果
这样就实现了仅接受“纯”A类型实例的需求,同时保留对C类型的原有错误校验。
内容的提问来源于stack exchange,提问作者iamkenos
相关产品推荐
相关产品推荐

