TypeScript+Node.js如何获取interface键列表并过滤请求体多余参数
TypeScript 所有类型(包括 interface、type 定义)仅存在于编译阶段,编译为 JavaScript 后会被完全擦除,因此你无法直接打印纯类型KnownKeysOfAnother得到键列表,下面提供两种可落地的解决方案:
方案1:手动维护键数组(无第三方依赖)
该方案不需要引入编译插件或第三方库,通过TS内置的校验能力保证键数组和interface定义完全一致:
interface IFooReal { prop1: string; prop2: number; } // 定义键数组,用as const锁定字面量类型,satisfies保证和interface的键完全匹配(TS 4.9+支持) const IFooRealKeys = ['prop1', 'prop2'] as const satisfies Array<keyof IFooReal>; // 可直接打印运行时存在的键数组 console.log(IFooRealKeys) // 输出 ['prop1', 'prop2'] // 编写通用属性过滤函数 function pick<T, K extends keyof T>(rawObj: unknown, allowedKeys: readonly K[]): T { const filtered = {} as T; if (typeof rawObj !== 'object' || rawObj === null) return filtered; for (const key of allowedKeys) { if (key in rawObj) { filtered[key] = (rawObj as Record<K, unknown>)[key] as T[K]; } } return filtered; }
在接口中使用:
documentRouter.post('/', async (req, res) => { const myObjet: IFooReal = pick(req.body, IFooRealKeys); // myObjet仅保留IFooReal定义的prop1、prop2属性 });
方案2:运行时校验库(推荐接口场景使用)
如果需要同时做参数格式校验,可以使用zod这类运行时校验库,同时满足类型推导、属性过滤、参数校验三个需求:
import z from 'zod'; // 先定义运行时可访问的schema const FooRealSchema = z.object({ prop1: z.string(), prop2: z.number() }); // 从schema推导出TS类型,效果和手写interface完全一致 type IFooReal = z.infer<typeof FooRealSchema>; // 可直接获取键列表 const IFooRealKeys = Object.keys(FooRealSchema.shape); console.log(IFooRealKeys) // 输出 ['prop1', 'prop2']
在接口中使用,自动过滤多余属性同时校验参数格式:
documentRouter.post('/', async (req, res) => { const parseResult = FooRealSchema.safeParse(req.body); if (!parseResult.success) { return res.status(400).json({ error: '参数格式错误' }); } const myObjet = parseResult.data; // myObjet仅保留IFooReal定义的属性,且prop1、prop2的类型经过校验 });
如果确实需要通过TS Transformation插件实现,可基于TypeScript官方编译器API在构建阶段扫描interface的AST生成对应键数组,但该方案维护成本较高,中小项目不推荐使用。
内容的提问来源于stack exchange,提问作者Luciano Castro
相关产品推荐
相关产品推荐

