TypeScript对象展开解构存疑:为何允许多余字段?
为什么对象展开赋值能通过TypeScript类型检查,直接字面量赋值却不行?
先看你提供的代码:
interface Person { name: string; age: number } interface UnknownPerson { age: number; } let me: Person = { name: "vilgeforc5", age: 19 } // 能通过类型检查 let anotherPerson: UnknownPerson = { ...me } console.log(anotherPerson.name) /* TypeScript报错,但运行时能正常输出 */ // 触发TypeScript错误 let anotherPerson2: UnknownPerson = { name: "vilgeforc5", age: 19 }
核心原因:TypeScript的「额外属性检查」机制
这是TypeScript的正常行为,和编译选项无关,差异来自两种赋值场景的类型检查逻辑不同:
直接字面量赋值时的严格检查
当你直接把对象字面量赋值给类型变量时,TypeScript会启动「额外属性检查」——它会严格校验字面量的所有属性是否都被目标类型定义,不允许存在未声明的额外属性。所以anotherPerson2里的name属性不在UnknownPerson的定义中,直接触发错误。变量展开赋值时的结构化类型兼容
而me是已经被标注为Person类型的变量,TypeScript这里会套用结构化类型系统的兼容规则:只要源类型包含目标类型的所有必填属性,源类型就可以赋值给目标类型。Person包含UnknownPerson要求的age属性,因此Person是UnknownPerson的兼容子类型,展开me后的对象可以赋值给anotherPerson。注意:运行时
anotherPerson确实会保留name属性,但TypeScript的类型系统会认为它是UnknownPerson类型,所以访问anotherPerson.name会触发类型错误,这是类型系统的静态约束,和运行时行为无关。
内容的提问来源于stack exchange,提问作者Boris Borais
相关产品推荐
相关产品推荐

