如何正确覆盖Prisma生成的User类型声明,解决SQLite环境下role字段类型限定问题
如何正确覆盖Prisma生成的User类型声明,解决SQLite环境下role字段类型限定问题
我太懂你这个困扰了——SQLite不支持Prisma的枚举类型,导致自动生成的User模型里role只能是个宽泛的string,明明想把它限定在"ADMIN"和"MEMBER"里,写了类型声明文件却只在显式标注User类型时生效,从Prisma查出来的用户实例还是用旧的string类型,简直让人头大!
问题出在哪?
你之前写的声明文件虽然重新导出了一个自定义的User类型,但Prisma客户端的查询方法(比如findUnique)返回的类型是基于它内部未被覆盖的原始User类型,和你重新导出的不是同一个。TypeScript的模块扩展规则里,单纯重导出并不能替换Prisma内部方法引用的类型,所以才会出现“一半生效一半不生效”的情况。
正确的解决方法
我们需要直接扩展Prisma内部的User模型接口,同时覆盖相关的输入类型,这样所有引用到User的地方都会自动更新成我们想要的类型。修改你的index.d.ts如下:
// index.d.ts import "@prisma/client"; declare module "@prisma/client" { // 先定义我们的限定类型 export type Role = "ADMIN" | "MEMBER"; // 直接扩展Prisma生成的User接口,替换role的类型 interface User { role: Role; } // 同时覆盖创建/更新用户时的输入类型,确保写入数据时也做类型校验 namespace Prisma { // 根据你实际用到的输入类型来扩展,下面是几个常用的示例 interface UserCreateInput { role: Role; } interface UserUpdateInput { role?: Role; } interface UserUncheckedCreateInput { role: Role; } interface UserUncheckedUpdateInput { role?: Role; } } }
为什么这样能行?
Prisma客户端的所有查询方法返回的类型,都是基于@prisma/client模块里的User接口生成的。直接扩展这个接口后,TypeScript会自动把所有引用到User的地方(包括查询返回结果、输入参数等)都替换成我们修改后的类型,完美解决之前的问题。
测试一下效果
现在再运行你之前的代码,就不会报错了:
import { PrismaClient, Role } from "@prisma/client"; const prisma = new PrismaClient(); async function getUser() { const user2 = await prisma.user.findUnique({ where: { id: 'someId' } }); if(!user2) return; const role2: Role = user2.role; // 这里TypeScript不会再报错! // 甚至创建用户时,还会自动校验role的取值 await prisma.user.create({ data: { id: "456", email: "test@example.com", role: "INVALID_ROLE" // 这里直接报TypeScript错误,不符合Role类型 } }); }
这样不管是显式声明User类型,还是从Prisma客户端查询返回的实例,role字段都会被正确限定在"ADMIN"和"MEMBER"里啦!
备注:内容来源于stack exchange,提问作者taxfree
相关产品推荐
相关产品推荐

