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

集成Prisma与tRPC时遇TS4058错误:返回类型无法命名

解决Prisma与tRPC集成时的TS4058类型错误

错误信息

TS4058: Return type of exported function has or is using name 'prisma' from external module "/Users/nils/Code/nextjs-coespace/node_modules/.prisma/client/index" but cannot be named

相关代码

Prisma客户端文件

// Note! This file has been copied from:
// https://github.com/prisma/prisma-examples/blob/latest/typescript/rest-nextjs-api-routes-auth/lib/prisma.ts

import { PrismaClient } from '@prisma/client';

// PrismaClient is attached to the `global` object in development to prevent
// exhausting your database connection limit.
//
// Learn more:
// https://pris.ly/d/help/next-js-best-practices

// eslint-disable-next-line import/no-mutable-exports
let prisma: PrismaClient;

if (process.env.NODE_ENV === 'production') {
  prisma = new PrismaClient();
} else {
  if (!global.prisma) {
    global.prisma = new PrismaClient();
  }
  prisma = global.prisma;
}

export default prisma;

tRPC控制器代码

import createRouter from '@/src/lib/server/trpc/routers/router';
import prisma from '@/src/lib/server/prisma';
import { z } from 'zod';

export default function locationRouter() {
  return createRouter()
    .mutation('create', {
      input: z.object({
        id: z.string().uuid(),
        // ...
      }),
      resolve(req) {
        return prisma.location.create({
          data: req.input,
        });
      },
    })
    .query('findMany', {
      resolve() {
          return prisma.location.findMany()
      },
    });
}

解决方案

方案1:显式指定路由返回类型

给tRPC的mutation和query添加返回类型定义,可通过Zod结构或直接指定Prisma模型类型实现:

方式A:用Zod定义输出结构

export default function locationRouter() {
  return createRouter()
    .mutation('create', {
      input: z.object({
        id: z.string().uuid(),
        // 其他输入字段
      }),
      // 显式定义输出结构
      output: z.object({
        id: z.string().uuid(),
        // 对应Location模型的其他字段
      }),
      resolve(req) {
        return prisma.location.create({
          data: req.input,
        });
      },
    })
    .query('findMany', {
      output: z.array(z.object({
        id: z.string().uuid(),
        // 对应Location模型的其他字段
      })),
      resolve() {
          return prisma.location.findMany()
      },
    });
}

方式B:直接指定Prisma模型类型

import { Location } from '@prisma/client';
import createRouter from '@/src/lib/server/trpc/routers/router';
import prisma from '@/src/lib/server/prisma';
import { z } from 'zod';

export default function locationRouter() {
  return createRouter()
    .mutation('create', {
      input: z.object({
        id: z.string().uuid(),
        // 其他输入字段
      }),
      resolve(req): Promise<Location> {
        return prisma.location.create({
          data: req.input,
        });
      },
    })
    .query('findMany', {
      resolve(): Promise<Location[]> {
          return prisma.location.findMany()
      },
    });
}

方案2:修正Prisma客户端的全局类型声明

在Prisma客户端文件中添加全局类型声明,让TypeScript正确识别global.prisma的类型:

import { PrismaClient } from '@prisma/client';

// 添加全局类型声明
declare global {
  var prisma: PrismaClient | undefined;
}

// eslint-disable-next-line import/no-mutable-exports
let prisma: PrismaClient;

if (process.env.NODE_ENV === 'production') {
  prisma = new PrismaClient();
} else {
  if (!global.prisma) {
    global.prisma = new PrismaClient();
  }
  prisma = global.prisma;
}

export default prisma;

方案3:临时关闭TypeScript的preserveValueImports选项(不推荐)

在tsconfig.json的compilerOptions中添加:

{
  "compilerOptions": {
    "preserveValueImports": false
  }
}

此方法可能影响其他代码的类型推断,仅作为临时应急方案使用。

错误原因

该错误是由于TypeScript无法解析Prisma客户端内部生成的未导出类型,导致在推断tRPC路由函数的返回类型时,无法为该类型命名。通过显式指定返回类型或修正全局类型声明,可让TypeScript正确识别相关类型,解决报错。

内容的提问来源于stack exchange,提问作者Nils Haberkamp

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 14:36:19