TypeScript实现MongoDB聚合project阶段的类型安全返回类型问题
解决MongoDB聚合Project阶段的类型推导问题
要实现projectActual()方法的正确返回类型推导,我们可以借助TypeScript的映射类型与条件类型,动态根据投影参数计算出最终的文档类型。
步骤1:定义投影类型工具
首先创建一个类型工具,用于从原始集合类型中提取投影后保留的字段:
type ProjectedType<Coll, Proj extends Record<keyof Coll, 0 | 1>> = { [K in keyof Coll as Proj[K] extends 1 ? K : never]: Coll[K] };
这个类型会遍历原始类型Coll的所有键,仅保留投影参数Proj中值为1的字段,生成投影后的目标类型。
步骤2:修改projectActual方法
为方法添加泛型参数捕获投影参数的具体类型,然后返回基于投影后类型的BaseAggregate实例:
class BaseAggregate<Coll> { private pipeline: any[] = []; // 替换为你实际的Pipeline类型定义 constructor(initialPipeline?: typeof this.pipeline) { if (initialPipeline) { this.pipeline = initialPipeline; } } match(stageInput: Partial<Coll>) { return new BaseAggregate<Coll>([...this.pipeline, { $match: stageInput }]); } projectActual<Proj extends Record<keyof Coll, 0 | 1>>(stageInput: Proj) { return new BaseAggregate<ProjectedType<Coll, Proj>>([ ...this.pipeline, { $project: stageInput }, ]); } }
验证示例
使用你的Test接口测试,此时agg的类型会自动推导为BaseAggregate<{ name: string }>:
interface Test { name: string; email: string; } const agg = new BaseAggregate<Test>() .match({ name: "john" }) .match({ email: "sir john" }) .match({ email: "sir" }) .projectActual({ email: 0, name: 1 });
扩展支持仅排除字段的场景
如果需要支持仅设置0来排除字段的投影(比如{ email: 0 }),可以调整ProjectedType为:
type ProjectedType<Coll, Proj extends Partial<Record<keyof Coll, 0 | 1>>> = { [K in keyof Coll as Proj[K] extends 0 ? never : K]: Coll[K] };
这样即使只传入排除字段的参数,也能正确推导剩余字段的类型。
内容的提问来源于stack exchange,提问作者Abd
相关产品推荐
相关产品推荐

