如何让TypeScript确认对象必然包含指定动态属性?
解决TypeScript中对象与属性键不匹配的类型错误
一、泛型重构方案(推荐)
通过泛型将useA的布尔值与对应的对象类型、属性键绑定,让TypeScript明确两者的关联关系,从根源上消除类型错误。这种方案扩展性强,后续新增类型时只需扩展映射规则即可。
重构后的代码示例:
type A = { a: string; } type B = { b: string; } // 定义布尔值到对象类型的映射 type TypeMap<T extends boolean> = T extends true ? A : B; // 定义布尔值到属性键的映射 type KeyMap<T extends boolean> = T extends true ? 'a' : 'b'; const getObj = function<T extends boolean>(useA: T): TypeMap<T> { if (useA) { return { a: 'test' } as TypeMap<T>; } else { return { b: 'test' } as TypeMap<T>; } } const getKey = function<T extends boolean>(useA: T): KeyMap<T> { if (useA) { return 'a' as KeyMap<T>; } else { return 'b' as KeyMap<T>; } } const getValue = function<T extends boolean>(useA: T): string { // 此时TypeScript能准确推断属性必然存在 return getObj(useA)[getKey(useA)]; }
二、类型断言方案
如果不想大规模重构代码,可以用类型断言直接告知TypeScript属性必然存在,适合快速临时解决问题:
相对安全的断言
const getValue = function(useA: boolean): string { // 断言返回对象包含getKey返回的键对应的字符串属性 return (getObj(useA) as Record<ReturnType<typeof getKey>, string>)[getKey(useA)]; }
简化但风险较高的断言
const getValue = function(useA: boolean): string { // 用any绕过所有类型检查,不推荐在复杂场景使用 return (getObj(useA) as any)[getKey(useA)]; }
三、行内禁用类型检查注释
若只是临时忽略该错误,可使用TypeScript的行内注释:
忽略该行所有类型错误
const getValue = function(useA: boolean): string { // @ts-ignore return getObj(useA)[getKey(useA)]; }
精准忽略特定错误代码
先查看报错的错误代码(比如2536),再针对性禁用:
const getValue = function(useA: boolean): string { // @ts-expect-error 2536 return getObj(useA)[getKey(useA)]; }
内容的提问来源于stack exchange,提问作者Dov Rosenberg
相关产品推荐
相关产品推荐

