TypeScript中如何从已知类型对象提取泛型指定属性?
TypeScript从已知对象提取泛型指定属性的实现方案
核心问题说明
TypeScript泛型是编译时特性,编译后会被完全擦除,因此无法直接通过泛型类型在运行时获取要提取的属性列表。必须结合运行时传入的属性名数组,同时通过泛型约束确保属性的合法性。
修正后的完整实现代码
interface IPerson { name: string; age: number; height: number; weight: number; job: string; } interface IAgeAndJob { age: number; job: string; } // 修正IHeightAndWeight的weight类型,与IPerson保持类型兼容 interface IHeightAndWeight { height: number; weight: number; } const person: IPerson = { name: 'Leon Kennedy', age: 21, height: 5.11, weight: 165, job: 'Police Officer' }; /** * 从对象中提取指定属性 * @param obj 源对象 * @param keys 需要提取的属性名数组 * @returns 包含指定属性的新对象 */ const mapProperties = <TObj, TKeys extends keyof TObj>(obj: TObj, keys: TKeys[]): Pick<TObj, TKeys> => { const result = {} as Pick<TObj, TKeys>; keys.forEach(key => { result[key] = obj[key]; }); return result; }; // 使用示例1:自动推断返回类型 const ageAndJob = mapProperties(person, ['age', 'job']); // ageAndJob类型为 Pick<IPerson, 'age' | 'job'>,与IAgeAndJob结构完全一致 // 使用示例2:断言为指定接口(需严格匹配时) const ageAndJob2 = mapProperties(person, ['age', 'job']) as IAgeAndJob; // 使用示例3:提取height和weight属性 const heightAndWeight = mapProperties(person, ['height', 'weight']) as IHeightAndWeight;
关键细节解释
- 泛型约束:
TKeys extends keyof TObj确保传入的属性名一定是源对象的有效键,避免出现不存在的属性报错。 - 运行时逻辑:必须传入属性名数组
keys,因为编译后泛型信息消失,只能通过这个数组明确要提取的属性。 - 返回类型:
Pick<TObj, TKeys>是TypeScript内置工具类型,自动生成包含指定属性的对象类型,无需手动重复定义接口。
原写法的问题分析
- 泛型参数
<IPerson, T>写法错误:第一个参数应为通用类型参数,而非具体接口名; - 仅通过
as T做类型断言,但实际返回空对象,没有真实的属性提取逻辑; - 缺少运行时属性列表,无法确定要提取哪些属性。
内容的提问来源于stack exchange,提问作者Katana24
相关产品推荐
相关产品推荐

