TypeScript扩展类型展开时多余属性保留的解决方法问询
TypeScript中如何过滤继承类型的额外属性
当把继承自B的类型A的对象展开到标注为B类型的变量时,TypeScript的编译时类型检查不会在运行时自动剔除A中额外的属性,导致输出仍然包含所有属性。比如:
interface B { name: string; } interface A extends B { age: number; } const fullThing: A = { age: 21, name: 'Bob' }; const thing: B = { ...fullThing }; console.log(thing); // 输出 { "age": 21, "name": "Bob" }
想要得到仅包含B类型属性的输出:{ "name": "Bob" },可以用以下几种方法:
方法1:手动提取目标属性
直接解构出B中定义的属性,适合属性数量少的场景:
// 直接赋值 const thing: B = { name: fullThing.name }; // 或者用对象解构简化 const { name } = fullThing; const thing: B = { name };
方法2:写通用过滤函数
如果B的属性较多,可以封装一个工具函数,传入目标对象和需要保留的属性列表来过滤:
function pick<T extends object, K extends keyof T>(obj: T, keys: K[]): Pick<T, K> { const result = {} as Pick<T, K>; keys.forEach(key => { if (key in obj) { result[key] = obj[key]; } }); return result; } // 使用时传入B的属性键 const thing: B = pick(fullThing, ['name']); console.log(thing); // { "name": "Bob" }
方法3:结合类型系统增强安全性
为了避免手动写错属性名,可以基于B类型定义一个受类型检查的属性键数组,再用它来过滤:
// 定义B的属性键数组,TypeScript会自动校验元素是否为B的合法属性 const BKeys = ['name'] as const satisfies readonly (keyof B)[]; function pickFrom<T, K extends readonly (keyof T)[]>(obj: T, keys: K): Pick<T, K[number]> { const result = {} as Pick<T, K[number]>; (keys as readonly string[]).forEach(key => { if (key in obj) { result[key as keyof T] = obj[key]; } }); return result; } const thing: B = pickFrom(fullThing, BKeys); console.log(thing); // { "name": "Bob" }
注意:TypeScript是编译时类型检查工具,运行时不存在类型信息,因此必须通过代码逻辑手动过滤属性,类型标注仅用于编译时校验,不会改变运行时对象的实际结构。
内容的提问来源于stack exchange,提问作者devklick
相关产品推荐
相关产品推荐

