TypeScript中如何用接口过滤对象属性?求非类实现方案
TypeScript 用接口过滤对象属性的解决方案
问题背景
假设有如下对象:
const A = { id: 123, name: "sample", foo: "test1", bar: "test2" }
以及定义的接口:
interface I { id: number; name: string; }
需要编写函数,过滤对象A得到仅包含接口I属性的新对象:
{ id: 123, name: "sample", }
尝试keyof特性未生效,求无需类的解决方案。
核心原因
TypeScript的接口是编译时类型,编译后会被完全移除,运行时无法直接获取接口的属性列表。所以单纯用keyof I只能在编译时做类型校验,没法直接用来过滤对象。
解决方案
我们需要同时提供编译时的类型约束和运行时的属性列表,结合两者实现过滤:
1. 定义接口属性的运行时数组
先创建一个包含接口I所有属性名的数组,用as const让TypeScript推断为字面量类型,确保数组内容和接口严格对应:
const iKeys = ['id', 'name'] as const;
2. 编写通用过滤函数
实现一个泛型函数,接收原对象和属性列表,返回仅包含指定属性的新对象,同时保证类型安全:
function pick<T, K extends keyof T>(obj: T, keys: readonly K[]): Pick<T, K> { const result = {} as Pick<T, K>; keys.forEach(key => { result[key] = obj[key]; }); return result; }
3. 使用函数过滤对象
调用函数时传入对象A和属性数组,得到符合接口I的对象:
const filteredA = pick(A, iKeys); // 此时filteredA的类型为I,值为{ id: 123, name: "sample" }
进阶:绑定接口I的严格版本
如果想让函数直接和接口I绑定,避免传入错误的属性数组,可以封装一层:
function pickFromI(obj: { [K in keyof I]: unknown }): I { return pick(obj, iKeys); } const filteredA = pickFromI(A);
这样既保证了运行时的过滤逻辑正确,又通过TypeScript的类型检查确保属性列表和接口完全一致,不会出现漏写或错写属性的情况。
内容的提问来源于stack exchange,提问作者Quasarity
相关产品推荐
相关产品推荐

