You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 05:26:15