TypeScript类型校验:对象传参与变量定义行为差异原因
这个行为差异来自TypeScript的多余属性检查(Excess Property Checking) 触发规则:这个校验只针对「直接使用对象字面量」的场景,常规的结构化类型兼容校验不会拦截额外属性。
常规结构化类型校验的逻辑
TypeScript的类型系统是结构化子类型系统,校验规则本质是「只要目标对象满足类型要求的所有结构,就判定兼容」,不会限制对象携带额外属性。
你第一段代码里,先声明myObj再传入函数的场景,走的就是这个常规校验:myObj确实存在label: string字段,完全满足printLabel函数读取argumentWithLabel.label的需求,额外的extraProperty不会对函数逻辑造成任何影响,所以编译可以正常通过。
对应可正常编译的代码:
type hasLabel = { label:string } function printLabel(argumentWithLabel:hasLabel) { console.log(argumentWithLabel.label); } let myObj = { extraProperty: "This is the extra property", label: "This is the label" }; printLabel(myObj);
对象字面量场景的特殊校验
当你直接把对象字面量赋值给带类型标注的变量、或者直接把对象字面量作为函数实参传入时,就会触发额外的多余属性检查。
这个规则是TypeScript专门加的错误捕获逻辑:开发者直接写对象字面量时,出现类型定义里不存在的属性,大概率是拼写错误、或者写了无用的冗余属性,属于需要拦截的低级bug。
你第二段代码直接给变量赋值对象字面量的写法,正好命中这个校验场景,所以会抛出错误:
// 以下代码会编译报错 let myObj:hasLabel = { extraProperty: "This is the extra property", label: "This is the label" };
报错信息也明确说明了触发逻辑:Object literal may only specify known properties,即对象字面量只能写类型里已声明的已知属性。
补充:哪怕你不提前声明变量,直接把同结构的对象字面量传给
printLabel,一样会触发这个报错,和是否赋值给变量无关,核心判断标准是你是不是在直接使用新创建的对象字面量。
内容的提问来源于stack exchange,提问作者oneday

