如何访问混合已知与未知字符串属性的TypeScript类型的字符串索引
解决方案:用交叉类型替代联合类型
你当前的问题出在使用了联合类型Foo | Bar——TypeScript对联合类型的索引访问有严格规则:只有当联合里的所有成员都支持该索引时,才能直接访问。Foo没有字符串索引签名,所以TypeScript无法确定foo到底是Foo还是Bar,自然不允许直接访问foo["txt"]。
要同时拥有固定属性和任意额外属性,且无需类型转换,应该用交叉类型把固定属性定义和索引签名合并,同时确保索引签名的类型覆盖固定属性的类型:
interface Foo { length: number; } // 交叉类型:合并固定属性与索引签名 type FooBar = Foo & { [key: string]: string | number; // 索引签名类型包含Foo中length的number类型 }; const foo: FooBar = { length: 1, txt: "TXT", numProp: 123 // 也能添加number类型的额外属性 }; const l = foo.length; // 正确推导为number类型 const txt = foo["txt"]; // 无报错,类型为string | number const randomProp = foo.randomKey; // 支持任意字符串索引
关键说明
- 交叉类型
&会把Foo的固定属性和索引签名合并成一个类型,TypeScript能明确识别:所有属性要么是Foo里的固定属性,要么是符合索引签名的额外属性。 - 索引签名的类型必须覆盖固定属性的类型(比如这里用
string | number,因为length是number,额外属性是string),否则会出现类型冲突报错。
如果你的额外属性只能是string类型,也可以调整定义,把固定属性的类型转为兼容索引签名的类型(比如给length加类型断言,但不符合业务逻辑的话不推荐),但上面的交叉类型方案是最通用的。
内容的提问来源于stack exchange,提问作者norman
相关产品推荐
相关产品推荐

