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
相关产品推荐
相关产品推荐

