如何让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生成的类型,编写针对特定查询结果的转换函数,避免误转:
- 保持你现有的codegen配置不变,确保生成的类型中
LocalDateTime被映射为Date类型。 - 编写类型安全的转换函数:
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
相关产品推荐
相关产品推荐

