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

TypeScript中类型安全的可选属性存在性检测方案是什么

类型安全的属性存在性检查实现方案

针对你的需求,以下是社区普遍采用的优雅、类型安全且兼容所有falsy值(false、0、空字符串等)的实现方案:

方案1:通用类型守卫函数(全TS版本兼容)

这是最通用的方案,封装一个类型安全的属性判断工具函数,TS会自动完成类型收窄和属性名校验:

/**
 * 类型安全的自有属性判断工具
 */
function hasProperty<T extends object, K extends PropertyKey>(
  obj: T,
  key: K
): obj is T & Record<K, T extends Record<K, infer V> ? V : unknown> {
  return Object.prototype.hasOwnProperty.call(obj, key);
}

改造后的业务代码:

async function updateCustomer(input: UpdateCustomerInput) {
  const customer = await getManager().findOneOrFail(Customer, input.customerId);

  if (hasProperty(input, 'name')) {
    customer.name = input.name;
  }
  if (hasProperty(input, 'age')) {
    customer.age = input.age;
  }
  if (hasProperty(input, 'admin')) {
    customer.admin = input.admin;
  }

  return getManager().save(Customer, customer);
}

这个方案的优势:

  • 完全类型安全:如果传入不存在的属性名,TS会直接抛出编译错误,不会出现手写字符串笔误的问题
  • 仅判断自有属性:避免in运算符会匹配原型链属性的隐患
  • 完美兼容falsy值:只要属性实际存在,哪怕值是false、0也会正常命中判断

方案2:批量解构赋值(属性对齐场景下最简洁)

如果输入参数的可选字段和Customer实体的字段完全对齐,可以用解构+Object.assign省略所有单个if判断,代码更简洁:

async function updateCustomer(input: UpdateCustomerInput) {
  const customer = await getManager().findOneOrFail(Customer, input.customerId);
  // 过滤掉不需要的customerId,剩余传入的字段直接合并
  const { customerId, ...updateFields } = input;
  Object.assign(customer, updateFields);
  return getManager().save(Customer, customer);
}

这个方案没有额外的工具函数依赖,同样类型安全,也完全兼容falsy值场景,适合字段匹配度高的更新场景。

方案3:TS 4.9+ 原生方法

如果你的项目TS版本 >=4.9,可以直接用原生的Object.hasOwn方法,不需要额外封装,已经内置了类型支持:

if (Object.hasOwn(input, 'name')) {
  customer.name = input.name;
}

效果和自定义的hasProperty工具函数完全一致。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 12:36:07