如何在TypeScript中定义支持MongoDB点语法查询的泛型校验类型
解决方案
核心依赖 TypeScript 4.1 及以上版本支持的模板字面量类型,递归生成模型所有合法的点分隔路径联合类型,即可实现需求。
1. 定义通用工具类型
首先实现两个通用工具类型,分别用于生成嵌套对象的全量合法路径、获取指定路径对应的值类型:
// 递归生成对象所有点分隔的合法路径 type DeepObjectPaths<T> = T extends object ? { [K in keyof T & (string | number)]: K | `${K}.${DeepObjectPaths<T[K]>}`; }[keyof T & (string | number)] : never; // 获取指定路径P对应的值类型 type PathValue<T, P extends string> = P extends `${infer K}.${infer Rest}` ? K extends keyof T ? PathValue<T[K], Rest> : never : P extends keyof T ? T[P] : never;
2. 实现支持点语法的Mongo查询过滤类型
基于上述工具类型实现最终的过滤类型,直接替换你原有定义的MongoManagerFilter即可:
export type MongoManagerFilter<T> = { [P in DeepObjectPaths<T>]?: PathValue<T, P>; };
3. 使用效果示例
代入你定义的UserModel测试,完全符合预期:
// 根属性查询 无类型错误 const filter1: MongoManagerFilter<UserModel> = { _id: '123' }; // 点语法嵌套查询 无类型错误 const filter2: MongoManagerFilter<UserModel> = { 'party.invites': 18 }; // 查询不存在的字段 直接触发TypeScript类型报错 const filter3: MongoManagerFilter<UserModel> = { 'party.invalid': 123 };
额外扩展说明
如果需要兼容MongoDB的查询操作符(比如$gt、$in等),仅需要调整值的类型即可,示例:
// 扩展支持操作符的版本 type MongoQueryValue<V> = V | { $gt?: V; $lt?: V; $in?: V[]; // 按需添加其他需要的操作符 }; export type MongoManagerFilter<T> = { [P in DeepObjectPaths<T>]?: MongoQueryValue<PathValue<T, P>>; };
内容的提问来源于stack exchange,提问作者user1779362
相关产品推荐
相关产品推荐

