GraphQL Scalars を使う
2021-12-3
#GraphQL
スカラ型
スカラ型とは、いくつかの種類がある GraphQL の型において最もプリミティブな値を表すものである。
組み込みスカラとカスタムスカラがある。
組み込みスカラ
以下の 5 種類の組み込みスカラが用意されている
- Int
- Float
- String
- Boolean
- ID
カスタムスカラ
scalar
キーワードを使うことで 独自のスカラ型を使用することができる。
どうシリアライズされるかやパースされるかは実装による。
GraphQL Scalars とは
カスタムスカラを提供してくれているパッケージ
実装
ドキュメント を参考
リゾルバー
// resolvers.ts
import { mergeResolvers } from '@graphql-tools/merge';
import { resolvers as scalarResolvers } from 'graphql-scalars';
export const resolvers = mergeResolvers([
scalarResolvers,
// ...
]);
スキーマ
// schemas.ts
import { loadFilesSync } from '@graphql-tools/load-files';
import { mergeTypeDefs } from '@graphql-tools/merge';
import { typeDefs as scalarsTypeDefs } from 'graphql-scalars';
import path from 'path';
const typesArray = loadFilesSync(path.join(__dirname, './**/*.graphql'));
const types = [scalarsTypeDefs, typesArray];
export const typeDefs = mergeTypeDefs(types);
使用したい graphql-scalars のカスタムスカラを定義
# schema.graphql
scalar EmailAddress
scalar DateTime
scalar URL
結果
適切にバリデーションされるようになる
# schemas.graphql
type User {
id: ID!
name: String!
email: EmailAddress!
birthDate: DateTime!
homePage: URL
}
type Query {
users(url: URL!): [User]!
}
email フィールドに適切な値で返ってこなかった場合
{
"errors": [
{
"message": "Value is not a valid email address: foo",
"locations": [
{
"line": 5,
"column": 5
}
],
"path": [
"users",
0,
"email"
],
"extensions": {
"code": "INTERNAL_SERVER_ERROR",
query などの引数に適切な値をとらなかった場合
{
"errors": [
{
"message": "Variable \"$url\" got invalid value \"bar\"; Expected type \"URL\". Invalid URL",
"locations": [
{
"line": 1,
"column": 13
}
],
"extensions": {
"code": "BAD_USER_INPUT",
"exception": {
"stacktrace": [
"TypeError: Invalid URL",
GraphQL Code Generator を使う時の Tips
そのまま型生成をしてしまうと any になってしまうので適切な型定義をする
// schemas.ts
// ・・・
export type Scalars = {
ID: string;
String: string;
Boolean: boolean;
Int: number;
Float: number;
DateTime: any;
EmailAddress: any;
URL: any;
};
// ・・・
any になるのを防ぐために設定の追加
defaultScalarType
を任意の型にすると、 any の代わりに設定した型になる
scalars
を設定すると、指定した型で上書きすることができる
# codegen.yml
config:
minify: true
defaultScalarType: unknown
scalars:
EmailAddress: string
// schemas.ts
// ・・・
export type Scalars = {
ID: string;
String: string;
Boolean: boolean;
Int: number;
Float: number;
DateTime: unknown;
EmailAddress: string;
URL: unknown;
};
// ・・・