TypeScript中能否实现通用属性检查类型守卫?
实现通用的属性检查类型守卫(TypeScript)
问题背景
我已经实现了针对单个属性的类型守卫,比如检查metadata属性的版本:
const hasMetadata = <T extends object>(obj: T): obj is T & {metadata: unknown} => ( Object.hasOwn(obj, 'metadata') )
但这类类型守卫需要写20多个,想做代码生成前,先确认TypeScript是否支持通用的属性检查类型守卫。我尝试了以下代码,但类型检查失败:
const hasProp = <T extends object>(obj: T, key: string): obj is T & {[key]: unknown} => ( Object.hasOwn(obj, key) )
报错信息:
A computed property name in a type literal must refer to an expression whose type is a literal type or a 'unique symbol' type
解决方案
可以通过添加泛型参数捕获具体键名来实现通用版本。核心是让TypeScript推断出key的字面量类型,而非宽泛的string类型:
const hasProp = <T extends object, K extends string | number | symbol>( obj: T, key: K ): obj is T & { [P in K]: unknown } => { return Object.hasOwn(obj, key); };
原理说明
- 新增泛型
K,约束为string | number | symbol(对象键的合法类型),TypeScript会自动推断传入key的具体字面量类型(比如传入'metadata'时,K就是'metadata')。 - 返回类型里的
{ [P in K]: unknown }是映射类型,会根据K的具体值生成对应的属性类型,避免了原代码中计算属性名类型不明确的问题。
使用示例
interface User { id: number; name: string; } const user: User = { id: 1, name: 'Alice' }; if (hasProp(user, 'age')) { // 这里user会被推断为User & { age: unknown } console.log(user.age); // 类型合法 }
内容的提问来源于stack exchange,提问作者Involture
相关产品推荐
相关产品推荐

