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

如何在TypeScript+Prisma中实现带类型安全的动态关联查询?

问题描述

我有丰富的Java后端开发经验,目前正在开发一个基于ExpressJS+TypeScript的后端项目,使用Prisma作为ORM。我写了一个根据ID查询Contract并动态包含指定关联的方法:

async findById(id: string, relations: string[] = []) {
  const includedRelations = relations.reduce((acc: Record<string, boolean>, curr: string) => {
    acc[curr] = true;
    return acc;
  }, {});

  return prisma.contract.findUnique({
    where: {
      id
    },
    include: includedRelations
  });
}

但调用该方法时,返回值仅为Prisma生成的基础Contract类型,不会包含指定的关联类型。我希望保留动态传入关联参数的能力,同时实现类型安全。尝试用type ContractWithRelations = Prisma.PromiseReturnType<typeof findById>定义类型,但它仍只识别基础Contract类型,无法感知包含的关联。请问该如何实现需求?

解决方案

要实现动态关联查询的类型安全,需要结合TypeScript泛型和Prisma自动生成的类型来约束参数并推导返回值类型,具体步骤如下:

1. 利用Prisma生成的关联类型

Prisma会为每个模型生成对应的[ModelName]Include类型(比如ContractInclude),它包含了该模型所有可关联的字段。我们可以用这个类型来约束传入的关联参数。

2. 改造方法为泛型函数

将findById改为泛型方法,通过泛型参数跟踪传入的关联字段,让TypeScript能准确推导返回值类型:

import { Prisma, Contract } from '@prisma/client';

async function findById<R extends Array<keyof Prisma.ContractInclude>>(
  id: string,
  relations: R = [] as R
): Promise<Prisma.ContractGetPayload<{ include: { [K in R[number]]: true } }>> {
  const includedRelations = relations.reduce((acc, curr) => {
    acc[curr] = true;
    return acc;
  }, {} as { [K in R[number]]: true });

  return prisma.contract.findUnique({
    where: { id },
    include: includedRelations
  });
}

3. 代码解释

  • 泛型参数R:约束relations参数只能是ContractInclude的键名数组,确保传入的关联字段都是合法的,避免拼写错误。
  • 返回值类型:使用Prisma.ContractGetPayload,它能根据传入的查询配置(这里是include的结构)推导最终的返回类型,自动包含指定的关联字段。
  • includedRelations类型:通过{ [K in R[number]]: true }精确描述包含的关联字段,让Prisma的类型系统能识别动态添加的关联,而不是当成模糊的Record<string, boolean>。

4. 使用示例

调用时,TypeScript会根据传入的relations自动推断返回值类型:

// 返回类型为 Contract & { client: Client; payments: Payment[] }
const contract = await findById('contract-id', ['client', 'payments']);

// 此时可以安全访问关联字段,不会有类型报错
console.log(contract.client.name);
console.log(contract.payments[0].amount);

这样既保留了动态传入关联的灵活性,又实现了完全的类型安全,返回值会准确包含指定的关联字段类型。

内容的提问来源于stack exchange,提问作者Nico Foth

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 01:52:37