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

如何让graphql-request将特殊标量类型字段转换为Date对象?

如何让graphql-request将特殊标量类型转换为Date对象

可以实现。graphql-request本身没有像Apollo Client那样内置标量类型的自动转换机制,但可以通过自定义响应转换逻辑或者结合GraphQL Code Generator生成类型安全的转换函数来达成目标。你当前codegen配置里的scalars仅做类型层面的别名映射,不会修改实际返回的数据;而typescript-resolvers插件是用于服务端Resolver类型生成,确实和客户端的graphql-request无关。

方案一:全局响应转换(通用但需注意误转)

通过graphql-request的transformResponse配置,递归遍历响应数据,将符合LocalDateTime格式的字符串转换为Date对象:

import { GraphQLClient } from 'graphql-request';

// 递归转换所有符合ISO 8601格式的字符串为Date
const transformLocalDateTimeToDate = (data: any): any => {
  if (typeof data !== 'object' || data === null) return data;
  
  if (Array.isArray(data)) {
    return data.map(item => transformLocalDateTimeToDate(item));
  }

  const transformed: Record<string, any> = {...data};
  for (const key in transformed) {
    const value = transformed[key];
    // 匹配LocalDateTime常见的ISO格式(如2024-05-20T12:34:56)
    if (typeof value === 'string' && /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?$/.test(value)) {
      transformed[key] = new Date(value);
    } else {
      transformed[key] = transformLocalDateTimeToDate(value);
    }
  }
  return transformed;
};

// 创建带转换逻辑的客户端实例
const client = new GraphQLClient('你的GraphQL端点URL', {
  transformResponse: (response) => {
    return transformLocalDateTimeToDate(response.data);
  }
});

这种方式无需依赖生成的类型,但会把所有符合格式的字符串转成Date,如果有其他同格式的非LocalDateTime字段可能会被误转。

方案二:类型安全的精准转换(推荐)

结合GraphQL Code Generator生成的类型,编写针对特定查询结果的转换函数,避免误转:

  1. 保持你现有的codegen配置不变,确保生成的类型中LocalDateTime被映射为Date类型。
  2. 编写类型安全的转换函数:
import type { GetUserQuery } from './src/gql/graphql'; // 替换为你生成的查询类型

// 针对GetUserQuery结果的转换
function transformGetUserResult(rawResult: GetUserQuery): GetUserQuery {
  const result = {...rawResult};
  
  // 转换用户的createdAt字段(假设该字段是LocalDateTime类型)
  if (result.user?.createdAt && typeof result.user.createdAt === 'string') {
    result.user.createdAt = new Date(result.user.createdAt) as unknown as Date;
  }
  
  // 递归处理嵌套对象或数组(比如用户的订单列表)
  if (result.user?.orders) {
    result.user.orders = result.user.orders.map(order => {
      if (order?.orderTime && typeof order.orderTime === 'string') {
        return {...order, orderTime: new Date(order.orderTime) as unknown as Date};
      }
      return order;
    });
  }
  
  return result;
}

// 使用示例
const rawResult = await client.request(GetUserDocument, { userId: 123 });
const transformedResult = transformGetUserResult(rawResult);

这种方式完全基于生成的类型,转换精准,但需要为每个查询编写对应的转换逻辑。

方案三:封装通用请求函数

把转换逻辑封装成通用请求函数,替代graphql-request的原生request方法:

import { request, DocumentNode } from 'graphql-request';

async function requestWithDate<T>(url: string, doc: DocumentNode, variables?: any): Promise<T> {
  const rawData = await request<T>(url, doc, variables);
  return transformLocalDateTimeToDate(rawData) as T;
}

// 使用示例
const result = await requestWithDate<GetUserQuery>('你的GraphQL端点URL', GetUserDocument, { userId: 123 });

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 11:03:13