如何为GraphQL日期标量的parseLiteral参数及ast指定类型?
解决NestJS GraphQL自定义日期标量中parseLiteral的类型问题
你遇到的问题核心是自定义的AST接口没有覆盖GraphQL规范中所有可能的ValueNode类型,导致TypeScript类型检查失败。正确的做法是直接使用graphql包提供的官方类型,并通过类型守卫来安全处理不同的节点类型。
步骤1:导入正确的类型
从graphql包中导入ValueNode以及具体的节点类型(比如IntValue、StringValue),这些类型已经覆盖了所有GraphQL值节点的情况:
import { CustomScalar, Scalar } from '@nestjs/graphql'; import { Kind, ValueNode, IntValue, StringValue } from 'graphql';
步骤2:正确实现parseLiteral方法
parseLiteral的参数类型应该是ValueNode,然后我们需要用类型守卫判断节点的具体类型,再做对应的处理:
- 对于
IntValue类型:将节点的value(字符串类型)转为数字后创建Date - 对于
StringValue类型:直接用字符串创建Date(支持ISO格式日期字符串) - 其他类型(比如
VariableNode):返回null或者抛出错误(根据你的业务需求)
完整的标量实现代码如下:
@Scalar('Date') export class DateScalar implements CustomScalar<number, Date> { description = 'Date custom scalar type that converts between Date objects and timestamps/ISO strings'; parseValue(value: number | string): Date { // 处理客户端传来的值(支持数字时间戳或ISO字符串) return new Date(value); } serialize(value: Date): number { // 发送给客户端时转为时间戳 return value.getTime(); } parseLiteral(ast: ValueNode): Date | null { // 处理查询字符串中的字面量 if (ast.kind === Kind.INT) { // 注意:IntValue的value是字符串类型,需要转为数字 return new Date(parseInt(ast.value, 10)); } if (ast.kind === Kind.STRING) { // 支持ISO格式的日期字符串,同时校验有效性 const date = new Date(ast.value); return isNaN(date.getTime()) ? null : date; } // 对于其他类型(比如变量节点),返回null或者抛出错误 return null; } }
为什么你的自定义AST接口会报错?
你定义的AST接口强制要求有value属性,但GraphQL的ValueNode类型包含了像VariableNode这样的节点——这类节点没有value属性(因为它是一个变量引用,不是字面量值)。所以TypeScript会提示类型不兼容,因为parseLiteral的参数可能是VariableNode,但你的接口要求必须有value。
使用官方的ValueNode类型并配合类型守卫,既能满足TypeScript的类型检查,又能正确处理所有可能的节点情况。
内容的提问来源于stack exchange,提问作者user3142695
相关产品推荐
相关产品推荐

