如何让TypeScript检测函数传入参数属性过多的错误?
TypeScript 严格类型校验:禁止传入含额外属性的参数
TypeScript 默认采用结构子类型规则:只要传入的参数包含目标类型的所有必填属性,即便有额外属性也不会触发类型错误。比如你给出的例子里,Type1 是 Type2 的超集,直接传入 foo 不会报错;用 Omit 生成的类型也存在同样问题。
要实现「严格校验,禁止额外属性」的需求,可以用以下两种方案:
方案一:自定义精确类型工具
通过 Exact 工具类型强制传入的类型与目标类型完全匹配,不允许有任何额外或缺失的属性:
interface Type1 { property1: string; property2: string; } interface Type2 { property1: string; }; // 精确类型工具:仅当 T 和 U 完全一致时才通过校验 type Exact<T, U> = T extends U ? U extends T ? T : never : never; // 用泛型约束参数必须严格匹配 Type2 function myFunction<T extends Type2>(params: Exact<T, Type2>) { console.log(params); } const foo: Type1 = { property1: 'foo1', property2: 'foo2', }; myFunction(foo); // ❌ 类型错误:Type1 包含额外属性 property2,与 Type2 不匹配
方案二:通过 never 约束禁止额外属性
给目标类型添加「所有非指定属性必须为 never」的交叉类型,直接阻断超集类型的传入:
interface Type1 { property1: string; property2: string; } interface Type2 { property1: string; }; // 生成严格版 Type2:禁止任何未定义的额外属性 type StrictType2 = Type2 & { [K in Exclude<keyof any, keyof Type2>]?: never; }; function myFunction(params: StrictType2) { console.log(params); } const foo: Type1 = { property1: 'foo1', property2: 'foo2', }; myFunction(foo); // ❌ 类型错误:property2 的类型 string 与 never 不兼容
针对 Omit 生成的类型
如果是用 Omit 生成的类型,同样可以套用上述方案:
interface Type1 { property1: string; property2: string; } // 用 Omit 生成基础类型 type Type2 = Omit<Type1, 'property2'>; // 转为严格类型 type StrictType2 = Type2 & { [K in Exclude<keyof any, keyof Type2>]?: never; }; function myFunction(params: StrictType2) { console.log(params); } const foo: Type1 = { property1: 'foo1', property2: 'foo2', }; myFunction(foo); // ❌ 触发类型错误
原理说明
TypeScript 的结构子类型规则允许超集类型赋值给子集类型,而上述方案通过以下逻辑打破这个规则:
Exact类型通过双向约束,确保传入类型和目标类型的属性完全一致;never约束则直接禁止任何未在目标类型中定义的属性存在。
内容的提问来源于stack exchange,提问作者JejeDev
相关产品推荐
相关产品推荐

