使用GraphQL Code Generator处理TypeScript中的日期
此文章的目的是什么?
在使用TypeScript和GraphQL Code Generator时,我发现很少有关于如何处理与日期相关的类型的文章,因此花费了一些时间才解决了这个问题。
一旦理解了,就觉得并不困难,但由于之前找不到相关资料,所以我将此作为备忘录。
环境
"graphql": "^16.6.0",
"graphql-scalars": "^1.20.1",
"graphql-yoga": "^3.1.1",
"@graphql-codegen/cli": "2.16.1",
最终版本的代码仓库
GraphQL 代码生成器
GraphQL Code Generator可以根据GraphQL的SDL生成相关的代码。
由于本次的主要目的是生成后端代码,因此需要在GraphQL Code Generator的配置文件codegen.ts中的plugins中指定’typescript-resolvers’。
const config: CodegenConfig = {
schema: 'schema.graphql',
generates: {
'./src/resolvers-types.ts': {
plugins: ['typescript', 'typescript-resolvers'],
},
},
...
}
}
设置如此后,使用yarn graphql-codegen可以根据下面展示的GraphQL的SDL生成包含解析器的类型定义文件。
type Task {
id: ID
content: String!
hasDone: Boolean!
}
type Query {
drafts: [Task!]
}
...
export type Query = {
__typename?: "Query";
drafts: Maybe<Array<Task>>;
};
export type Task = {
__typename?: "Task";
content: Scalars["String"];
hasDone: Scalars["Boolean"];
id: Maybe<Scalars["ID"]>;
};
...
export type TaskResolvers<
ContextType = any,
ParentType extends ResolversParentTypes["Task"] = ResolversParentTypes["Task"]
> = {
content?: Resolver<ResolversTypes["String"], ParentType, ContextType>;
hasDone?: Resolver<ResolversTypes["Boolean"], ParentType, ContextType>;
id?: Resolver<Maybe<ResolversTypes["ID"]>, ParentType, ContextType>;
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
};
...
在这种情况下,如果在Resolver中指定如下,就可以根据生成的类型来实现Resolver。
export const TaskResolever: QueryResolvers['drafts'] = () => {
/// Taskを返す処理
}
用GraphQL的SDL来定义与日期相关的属性。
GraphQL的默认标量值只准备了以下选项。
-
- Int
-
- Float
-
- String
-
- Boolean
- ID
因此,當需要處理Date或DateTime等時,需要作為自定義標量進行添加。
自定義標量的定義如下所示。
scalar DateTime # この部分
scalar Date # この部分
type Task {
id: ID
content: String!
hasDone: Boolean!
createdAt: DateTime! # Custom Scalarを参照
createdOn: Date! # Custom Scalarを参照
}
type Query {
drafts: [Task!]
}
要将TypeScript类型设置为CutomScalar,在codegen.ts中需要指定Date和DateTime的类型。需要注意的是,这里的定义方式不是使用对象的类型,而是使用字符串的形式。也就是说,需要指定的是’Date’而不是Date。
...
const config: CodegenConfig = {
...
scalars: {
DateTime: 'Date',
Date: 'Date'
}
}
};
...
如果想要防止Custom Scalar成为any类型的情况,可以将strictScalars选项设置为true,在代码生成时,当Custom Scalar的类型为any时,会抛出错误。
...
const config: CodegenConfig = {
...
strictScalars: true, // この部分を追加
scalars: {} // Date, DateTimeの定義がない場合
}
};
...
GraphQL标量
在TypeScript中,经常使用的自定义标量是GraphQL Scalars包,它提供了Date和DateTime的定义,您可以利用它们。
在上述的schema.graphql中,answeredAt被指定为DateTime类型,而answeredOn被指定为Date类型。但在TypeScript的代码中,它们都以Date类型返回。
似乎两者都返回了new Date().toString()的值。为了返回期望的值,需要添加GraphQL Scalars的类型定义和解析器。
结束
如果在GraphQL Code Generator中处理日期和时间类型时,使用GraphQL Scalars,就不需要自己定义格式,非常方便。
但是,理解如何使用这些类型在官方文档中确实有一定困难,如果能帮助到其他遇到同样问题的人,我会很高兴。
附言
出于以下原因,我暂时不会处理GraphQL Code Generator。