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

TypeScript按键名给类属性赋值时类型报错问题求助

问题描述

我有两个对象:一个是CreateUserDto类的实例,另一个是IUser接口类型的对象。IUser包含诸多CreateUserDto不具备的属性。我希望利用IUser对象创建并填充CreateUserDto实例中两者共有的属性,为此编写了如下代码:

// user是IUser类型,createUserDto是CreateUserDto类型
Object.keys(user).filter(key => key in createUserDto).forEach(key => {
        // key仅包含两者共有的属性键,且对应类型一致
        let test = createUserDto[key as keyof CreateUserDto];
        let test2 = user[key as keyof CreateUserDto];

        // 以下两行可正常运行
        test = test2;
        test = user[key as keyof CreateUserDto];
        
        // 以下两行无法运行...
        createUserDto[key as keyof CreateUserDto] = test2;
        createUserDto[key as keyof CreateUserDto] = user[key as keyof CreateUserDto];
      });

但最后两行代码报错,错误信息如下:

createUserDto[key as keyof CreateUserDto] = test2;

Type 'string | number | boolean | Permission[] | Date | UserGroup[] | undefined' is not assignable to type 'never'.
  Type 'undefined' is not assignable to type 'never'.ts(2322)
createUserDto[key as keyof CreateUserDto] = user[key as keyof CreateUserDto];

Type 'string | number | boolean | Permission[] | Date | UserGroup[] | undefined' is not assignable to type 'never'.ts(2322)
问题原因与解决方案

问题原因

  1. 类型收窄失效:Object.keys(user)返回的是string[],即便用filter过滤出CreateUserDto的共有键,TypeScript也无法将这些键精确收窄到keyof CreateUserDto的子集。key as keyof CreateUserDto只是强制断言,但TypeScript无法确定当前key对应的具体属性类型,只能推断为所有CreateUserDto属性类型的联合。赋值时,TypeScript会检查值是否能兼容所有可能的属性类型,最终得出never类型(没有类型能同时兼容所有联合成员),因此报错。
  2. 变量与对象属性赋值的差异:前两行test = test2能运行,是因为test和test2的类型都是CreateUserDto[keyof CreateUserDto](所有属性类型的联合),联合类型之间可以互相赋值;但直接给对象属性赋值时,TypeScript需要确保值的类型完全匹配当前属性的具体类型,此时类型信息已丢失,所以触发错误。

解决方案

方法1:用泛型函数精准处理属性赋值

编写泛型函数让TypeScript跟踪具体的键类型,确保赋值类型匹配:

function assignProperty<T, K extends keyof T>(obj: T, key: K, value: T[K]) {
  obj[key] = value;
}

// 遍历赋值
Object.keys(user).forEach(key => {
  if (key in createUserDto) {
    const typedKey = key as keyof CreateUserDto;
    assignProperty(createUserDto, typedKey, user[typedKey] as CreateUserDto[keyof CreateUserDto]);
  }
});

方法2:使用Object.assign(简洁高效)

如果CreateUserDto的共有属性类型和user完全匹配,直接用Object.assign更简单,TypeScript能正确处理类型:

Object.assign(createUserDto, user);

注:Object.assign会把user的所有可枚举属性赋值给createUserDto,但CreateUserDto没有的属性会被忽略(运行时不会添加到实例上),刚好符合需求。

方法3:类型断言跳过检查(适合确定类型安全的场景)

如果能确保类型完全一致,可以用any断言跳过类型检查:

Object.keys(user).filter(key => key in createUserDto).forEach(key => {
  const typedKey = key as keyof CreateUserDto;
  (createUserDto[typedKey] as any) = user[typedKey];
});

内容的提问来源于stack exchange,提问作者sirzento

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 04:09:29