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

如何将Prisma的Json类型字段映射到TypeGraphQL自定义对象类型?

解决方案

这种定义方式完全可行,核心是在Prisma数据和TypeGraphQL类型之间做手动类型转换——因为Prisma返回的Json?字段对应Prisma.JsonValue类型,和你定义的Comment[]类型不兼容,必须显式转换才能匹配TypeGraphQL的类型要求。

具体实现步骤

1. 实现类型转换工具函数

先写一套工具函数,负责JSON数据和Comment类型的双向转换,同时加入类型校验避免运行时错误:

import { Prisma } from '@prisma/client';
import { Comment } from './types';

// 类型守卫:检查对象是否符合Comment结构
function isComment(obj: unknown): obj is Comment {
  return (
    typeof obj === 'object' &&
    obj !== null &&
    'id' in obj && typeof (obj as Comment).id === 'number' &&
    'content' in obj && typeof (obj as Comment).content === 'string'
  );
}

// 把Prisma返回的JsonValue转换成Comment[]
export function parseComments(comments: Prisma.JsonValue | null | undefined): Comment[] | null {
  if (!comments) return null;
  if (!Array.isArray(comments)) return null;
  // 验证每个元素的结构合法性
  return comments.every(isComment) ? (comments as Comment[]) : null;
}

// 把Comment[]转换成Prisma可存储的JsonValue
export function stringifyComments(comments: Comment[] | null | undefined): Prisma.JsonValue | null {
  if (!comments) return null;
  return JSON.parse(JSON.stringify(comments)) as Prisma.JsonValue;
}

2. 修改Resolver完成类型映射

你原来的Resolver直接返回了Prisma的PostDb类型,和TypeGraphQL定义的Post类型不匹配,需要手动转换字段:

import { Post as PostDb } from '@prisma/client';
import { Post, Comment } from './types';
import { parseComments, stringifyComments } from './utils';

@Resolver(Post)
export class PostResolver {
  @Query((returns) => Post, { nullable: true })
  async getPostByTitle(@Arg('title') title: string): Promise<Post | null> {
    try {
      const postDb = await prismaClient.post.findUnique({
        where: { title }
      });
      if (!postDb) return null;
      // 转换PostDb到Post类型,重点处理comments字段
      return {
        ...postDb,
        comments: parseComments(postDb.comments)
      };
    } catch(error) {
      throw new GetPostError(error.message);
    }
  }

  // 示例:创建Post时的反向转换
  @Mutation((returns) => Post)
  async createPost(
    @Arg('title') title: string,
    @Arg('content') content: string,
    @Arg('comments', { nullable: true }) comments?: Comment[]
  ): Promise<Post> {
    const postDb = await prismaClient.post.create({
      data: {
        title,
        content,
        comments: comments ? stringifyComments(comments) : null
      }
    });
    return {
      ...postDb,
      comments: parseComments(postDb.comments)
    };
  }
}

3. 解决TypeScript类型报错

通过上述转换,Resolver返回的类型完全匹配TypeGraphQL定义的Post类型,TypeScript的类型不兼容错误会直接消失。同时isComment类型守卫能确保从JSON解析出来的数据符合预期结构,避免非法数据导致运行时异常。

关键注意事项

  • 必须处理双向转换:查询时把JSON转成Comment[],写入时把Comment[]转成JSON格式。
  • 类型守卫是可选但推荐的:用于验证JSON数据的结构合法性,避免脏数据引发问题。
  • 不要直接返回Prisma模型:TypeGraphQL依赖你定义的@ObjectType()类,必须做字段映射转换。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 22:10:24