TypeScript疑问:为何符合结构的Obj类型无法传入Record参数函数?
TypeScript类型错误原因解析
先看代码:
const func: (prm: Record<string, string | number>) => void = (prm) => { return; }; interface Obj { key1: string; } func({ key1: 'value1' } as Obj); // 类型错误:Argument of type 'Obj' is not assignable to parameter of type 'Record<string, string | number>'. Index signature for type 'string' is missing in type 'Obj'.ts(2345)
为什么会报错?
核心在于两个类型的约定范围不一样:
Record<string, string | number>是带字符串索引签名的类型,它向TypeScript做出承诺:不管用什么字符串当键去访问这个对象,得到的属性值一定是string或number。换句话说,函数func内部完全可以随便写prm['任意字符串键'],TypeScript会保证这个操作的结果符合类型要求。- 而
Obj接口只定义了key1: string,没有索引签名。TypeScript对Obj的理解是:这个类型的对象至少有key1属性,但可能还有其他属性,且其他属性的类型不做限制。比如有人可以这么写:
这段代码TypeScript不会报错,因为结构类型允许额外属性。但如果把这个const obj: Obj = { key1: 'test', key2: true };obj传给func,当func访问prm['key2']时,得到的是布尔值,直接违反了Record<string, string | number>的约定。
你觉得Obj结构满足要求,是因为只看了当前传入的那个具体对象,但TypeScript的类型检查是基于类型本身的约定,不是某个实例的结构。Obj没承诺"所有字符串键的属性都是string/number",所以和Record<string, string | number>不兼容。
怎么解决?
如果要让Obj能传给func,给它加上字符串索引签名就行:
interface Obj { key1: string; [key: string]: string | number; // 明确所有字符串键的属性类型 }
内容的提问来源于stack exchange,提问作者mannok
相关产品推荐
相关产品推荐

