如何移除TypeScript联合类型未列出的对象属性?
TypeScript中如何根据联合类型过滤对象属性,保留指定字段?
我原本以为这在TypeScript中无法实现,但或许有误,故提出如下问题:
假设有一个对象示例:
const person = { name: "Feter Pox", city: "Berlin", age: "30", };
该对象为普通对象,可按需修改,只要能正常访问name等属性即可。
同时存在一个不可修改的联合类型:
type keys = 'name' | 'age';
注意:无法将数组['name', 'age']转换为该keys类型来解决问题,因为不存在这样的数组。
需求:创建person的副本reducedPerson,仅保留keys中列出的属性,未列出的属性需完全移除。
预期结果:
const reducedPerson = { name: "Feter Pox", age: "30", };
我尝试的方法无效:
const person = { name: "Feter Pox", city: "Berlin", age: "30", }; type keys = 'name' | 'age'; const reducedPerson: Record<keys, string> = person; reducedPerson. // 优点:自动补全仅提示'name'和'age',无'city' console.log(reducedPerson); // 缺点:对象中仍存在'city'属性
可行解决方案
方案一:手动提取属性(适合字段较少的场景)
直接手动复制需要保留的属性,同时用Pick类型约束结果的类型,既能保证类型安全,又能彻底移除多余属性:
const person = { name: "Feter Pox", city: "Berlin", age: "30", }; type keys = 'name' | 'age'; const reducedPerson: Pick<typeof person, keys> = { name: person.name, age: person.age }; console.log(reducedPerson); // 输出:{ name: "Feter Pox", age: "30" }
方案二:通用工具函数(适合复用场景)
写一个通用的pick函数,手动传入需要保留的字段参数,结合类型断言实现类型安全的属性过滤:
const person = { name: "Feter Pox", city: "Berlin", age: "30", }; type keys = 'name' | 'age'; function pick<T, K extends keyof T>(obj: T, ...keys: K[]): Pick<T, K> { const result = {} as Pick<T, K>; keys.forEach(key => { result[key] = obj[key]; }); return result; } // 手动传入字段参数,同时指定类型参数确保和keys类型匹配 const reducedPerson = pick<typeof person, keys>(person, 'name', 'age'); console.log(reducedPerson); // 输出:{ name: "Feter Pox", age: "30" }
说明
因为TypeScript的类型仅存在于编译阶段,没有运行时的对应数组的话,无法自动从keys类型生成需要保留的字段列表,必须手动指定要保留的字段。但通过上述方法,可以同时保证类型校验正确和实际对象无多余属性的需求。
内容的提问来源于stack exchange,提问作者Page not found
相关产品推荐
相关产品推荐

