MongoDB子对象过滤时的TypeScript类型校验问题
解决MongoDB查询时TypeScript类型校验失效的问题
方案1:自定义类型约束生成合法路径
自己实现递归工具类型推导对象的所有合法点分隔路径,约束查询条件的键必须属于这些合法路径:
// 递归生成对象的所有合法点路径 type ObjectPath<T> = T extends object ? { [K in keyof T & (string | number)]: | `${K}` | `${K}.${ObjectPath<T[K]>}` }[keyof T & (string | number)] : never; // 定义User类型的合法查询路径集合 type UserQueryPath = ObjectPath<User>; // 约束查询条件的键只能是合法路径 type UserFilter = Partial<Record<UserQueryPath, unknown>>; // 查询时强制类型约束 const users: User[] = await collection.find({ 'userData.username': username } as UserFilter).toArray();
修改User接口的字段后,若查询路径拼写错误,TypeScript会直接标记类型错误。
方案2:用嵌套对象查询替代点路径
直接通过嵌套对象构造查询条件,TypeScript会自动校验嵌套字段的合法性,同时和点路径查询效果一致:
// 匹配userData中username字段等于目标值 const users: User[] = await collection.find({ userData: { username: username } }).toArray();
这种写法无需字符串路径,字段名修改后TypeScript会立即提示错误。
方案3:结合MongoDB官方驱动的Filter泛型
利用MongoDB Node.js驱动提供的Filter泛型,搭配自定义路径类型强化校验:
import { Filter } from 'mongodb'; // 递归生成对象的所有合法点路径 type ObjectPath<T> = T extends object ? { [K in keyof T & (string | number)]: | `${K}` | `${K}.${ObjectPath<T[K]>}` }[keyof T & (string | number)] : never; // 扩展Filter类型,添加点路径的类型约束 type FilterWithDotPaths<T> = Filter<T> & Partial<Record<ObjectPath<T>, unknown>>; // 查询时使用扩展后的类型 const users: User[] = await collection.find({ 'userData.username': username } as FilterWithDotPaths<User>).toArray();
该方案既保留MongoDB原生查询的灵活性,又实现了点路径的类型校验。
内容的提问来源于stack exchange,提问作者Luca Gambaro
相关产品推荐
相关产品推荐

