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

TypeScript对象属性覆盖类型问题求助:实现非空属性赋值函数

解决TypeScript中assignIfPresent函数的类型错误问题

你的问题核心在于TypeScript无法识别你对additions[propName]的过滤逻辑,从而认为赋值时可能存在undefined类型不匹配的情况。让我们一步步拆解并解决这个问题:

为什么会报错?

你定义的additions是Partial<T>类型,这意味着它的每个属性都是可选的,类型为T[K] | undefined。虽然你写了if (additions[propName])来过滤,但TypeScript的控制流分析在这里不够智能:

  1. 这个条件会排除所有"假值"(比如0、''、false等),但你实际想要的是排除null和undefined
  2. 即使条件成立,TypeScript也无法自动将additions[propName]的类型从T[K] | undefined缩小到T[K]

解决方案:精确的类型守卫+类型缩小

我们可以通过两个步骤修复这个问题:

  1. 用精确的条件判断只排除null和undefined(避免误过滤合法的假值)
  2. 用类型谓词函数让TypeScript明确知道过滤后的值是合法的T[K]类型

完整代码实现

// 定义一个类型谓词函数,用来判断值不是null或undefined
function isNotNullOrUndefined<T>(value: T | null | undefined): value is T {
  return value !== null && value !== undefined;
}

function assignIfPresent<T extends Record<string, unknown>>(origObj: T, additions: Partial<T>) {
  for (const propName in additions) {
    const value = additions[propName];
    // 使用类型谓词函数进行类型缩小
    if (isNotNullOrUndefined(value)) {
      origObj[propName] = value;
    }
  }
  return origObj;
}

简化版(使用类型断言)

如果你不想额外定义类型谓词函数,也可以直接在赋值时使用类型断言(适合简单场景):

function assignIfPresent<T extends Record<string, unknown>>(origObj: T, additions: Partial<T>) {
  for (const propName in additions) {
    const value = additions[propName];
    if (value !== null && value !== undefined) {
      origObj[propName] = value as T[keyof T];
    }
  }
  return origObj;
}

验证你的使用案例

用修改后的函数运行你的测试代码:

class User {
  public firstName!: string;
  public lastName!: string;
  public gender?: string;
}
const newUser = new User();
newUser.lastName = "Biden"
const userDetails: Partial<User> = { firstName: "Joe", lastName: undefined, }
console.log(assignIfPresent(newUser, userDetails)) // 输出: { "lastName": "Biden", "firstName": "Joe" }
console.log({...newUser, ...userDetails}) // 输出: { "firstName": "Joe" }

完全符合你的预期:userDetails中的undefined不会覆盖newUser原有的lastName值,而有效的firstName会被正确赋值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 08:02:49