集成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
相关产品推荐
相关产品推荐

