为何TypeScript中接口与对象类型继承Record<string,string>结果不同?
TypeScript中Interface与对象字面量extends Record<string, string>的差异原因
先明确两个核心前提:
Record<string, string>是索引签名类型,要求类型的所有属性(包括任意新增的string键属性)必须全为string类型。- TypeScript对interface和对象字面量类型的处理逻辑有本质区别:
1. 对象字面量类型的判断逻辑
当用{ userId: string, hedgerId: string }这种对象字面量类型做extends判断时,TypeScript会把它视作封闭的、属性固定的类型——它的属性只有userId和hedgerId,且都是string类型,完全满足Record<string, string>的要求,因此条件判断返回true。
2. Interface的判断逻辑
Interface在TypeScript中是开放的、可扩展的类型。哪怕你定义时只写了userId和hedgerId两个string属性,TypeScript默认允许后续通过声明合并给这个interface添加新属性(比如后续再写interface IProps { age: number })。
在条件类型IProps extends Record<string, string> ? true : false的判断中,TypeScript会考虑这种“可扩展”的可能性:如果后续给IProps添加了非string类型的属性,它就不符合Record<string, string>的要求了。因此这个条件判断返回false——因为IProps无法保证所有属性(包括未来可能新增的)都是string类型。
举个直观的验证例子:
interface IProps { userId: string hedgerId: string } // 声明合并,给IProps新增number类型属性 interface IProps { age: number } type a = IProps extends Record<string, string> ? true : false // a依然是false,因为age是number,不符合索引签名要求
这就是两种写法结果不同的根本原因:interface是开放可扩展的,而对象字面量类型是封闭固定的,导致它们在extends索引签名类型时的判断逻辑完全不一样。
内容的提问来源于stack exchange,提问作者morgs32
相关产品推荐
相关产品推荐

