You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修复访问对象成员时出现的‘类型无法赋值给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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 06:20:51