如何将Prisma查询返回的字符串转换为TypeScript枚举?
Prisma字符串字段与TypeScript枚举类型不匹配的解决方案
方案1:使用Prisma原生枚举类型(推荐)
直接在Prisma Schema中定义枚举,替代单独的TS枚举,生成的客户端类型会自动对齐,查询返回的字段直接是枚举类型,无需额外转换。
修改Prisma Schema:
enum Status { OK ERROR } model User { id String @id @default(uuid()) status Status? @db.VarChar(20) // 仍可指定数据库存储类型为VarChar }
重新生成Prisma客户端:
npx prisma generate
之后直接使用Prisma生成的Status枚举,查询返回的user.status类型自动匹配,无类型错误:
import { Status } from '@prisma/client'; const user = await prisma.user.findFirst({ where: { id: 'uuidhere' } }); return <MyComponent status={user.status} />;
优点:类型完全对齐,无需手动维护TS枚举与数据库字段的一致性,Prisma自动处理映射。
缺点:若使用MySQL等数据库,原生枚举会绑定数据库枚举,修改枚举值需执行数据库迁移。
方案2:通过TypeScript模块扩充覆盖Prisma类型
若不想修改数据库枚举类型,可通过TS模块扩充,将Prisma生成的User类型中的status字段替换为自定义Status枚举,实现类型层面对齐。
步骤:
- 保留原有TS枚举定义:
export enum Status { OK = 'ok', ERROR = 'error', }
- 创建类型扩充文件(如
prisma-types.d.ts):
import { Prisma } from '@prisma/client'; import { Status } from './your-enum-file'; declare module '@prisma/client' { interface User { status?: Status; } // 扩充客户端操作类型,确保写入时也支持枚举 interface PrismaClient { user: Omit<Prisma.UserDelegate, 'create' | 'update' | 'updateMany'> & { create: Prisma.UserCreateDelegate<{ status?: Status }>; update: Prisma.UserUpdateDelegate<{ status?: Status }>; updateMany: Prisma.UserUpdateManyDelegate<{ status?: Status }>; }; } }
此后所有查询返回的User对象的status字段,都会被TS识别为Status枚举,无需手动转换或断言。
优点:无需修改数据库或Prisma Schema,仅通过类型层面解决问题。
缺点:需维护类型扩充代码,若Prisma Schema变更需同步更新扩充逻辑。
方案3:使用Prisma中间件自动转换并验证
通过Prisma中间件,在查询返回结果时自动将字符串转为Status枚举,同时验证值的合法性,避免无效值流入业务代码。
实现中间件:
import { PrismaClient } from '@prisma/client'; import { Status } from './your-enum-file'; const prisma = new PrismaClient(); // 验证字符串是否为合法Status枚举值 const isValidStatus = (value: string): value is Status => { return Object.values(Status).includes(value as Status); }; prisma.$use(async (params, next) => { const result = await next(params); // 处理User模型的查询结果 if (params.model === 'User' && ['findUnique', 'findFirst', 'findMany'].includes(params.action)) { const transformStatus = (data: any) => { if (data?.status && isValidStatus(data.status)) { data.status = Status[data.status as keyof typeof Status]; } return data; }; // 兼容单条数据和数组结果 return Array.isArray(result) ? result.map(transformStatus) : transformStatus(result); } return result; });
配合方案2的类型扩充,可实现运行时自动转换+类型系统对齐,完全无需手动处理转换逻辑。
优点:自动处理所有查询结果,同时验证枚举值合法性,避免无效数据。
缺点:存在轻微运行时性能开销(可忽略),需维护中间件逻辑。
内容的提问来源于stack exchange,提问作者Sandy
相关产品推荐
相关产品推荐

