如何修复访问对象成员时出现的‘类型无法赋值给never’错误
TypeScript类型错误原因及优化修复方案
问题场景
我编写了如下TypeScript代码:
interface IFoo { bar: string; baz: number; } function f(foo: IFoo, name: 'bar' | 'baz', val: any) { foo[name] = val; // <<< error: Type 'any' is not assignable to type 'never'. }
当我将接口IFoo中baz的类型也改为string后,错误消失:
interface IFoo { bar: string; baz: string; } function f(foo: IFoo, name: 'bar' | 'baz', val: any) { foo[name] = val; // fine }
请问该错误出现的原因是什么?能否找到比将name: 'bar' | 'baz'替换为name: string更优的修复方案?
错误原因
当用联合类型'bar' | 'baz'作为属性名时,TypeScript会做严格的类型收缩校验:
- 对
foo[name]赋值时,TypeScript要求val的类型必须同时兼容bar的string类型和baz的number类型。 string和number的交集类型是never(没有任何值能同时属于这两种类型),而any类型无法赋值给never,因此抛出错误。- 当两个属性类型统一为
string后,交集类型就是string,any可以赋值给string,错误自然消失。
更优修复方案
方案1:泛型约束属性名与值的类型关联
通过泛型让TypeScript自动推断属性名对应的具体类型,确保值的类型和目标属性类型严格匹配,既保留属性名的枚举限制,又保证类型安全:
interface IFoo { bar: string; baz: number; } function f<K extends keyof IFoo>(foo: IFoo, name: K, val: IFoo[K]) { foo[name] = val; // 完全类型安全,无错误 } // 使用示例 const foo: IFoo = { bar: "hello", baz: 123 }; f(foo, "bar", "world"); // 正确:值为string,匹配bar的类型 f(foo, "baz", 456); // 正确:值为number,匹配baz的类型 f(foo, "bar", 789); // 报错:number不能赋值给string,类型校验生效
方案2:将val的类型设为属性类型的联合
如果不需要严格的一一对应,也可以把val的类型定义为IFoo['bar'] | IFoo['baz'](即string | number),让TypeScript允许符合任一属性类型的值:
interface IFoo { bar: string; baz: number; } function f(foo: IFoo, name: 'bar' | 'baz', val: string | number) { foo[name] = val; // 无错误 }
注意:这个方案的安全性略低于泛型方案,它允许给bar传入number(比如f(foo, 'bar', 123)不会报错),而泛型方案会严格阻止这类错误。
内容的提问来源于stack exchange,提问作者Nikolay
相关产品推荐
相关产品推荐

