この記事は弥生 Advent Calendar 2024の 1日目(シリーズ 2)のエントリーです。
こんにちは。弥生でエンジニアをしている福嶋です。
今年2月に入社してから9カ月が経ちまして、あっという間にアドベントカレンダーの時期になっていました。月日が経つの早すぎない?
今まで REST API を扱っていましたが、弥生に入社してから初めて GraphQL に触れています。
TypeScript を使っているので GraphQL 周りが型安全になるよう試行錯誤したのですが、今回は TypedDocumentNode を使って GraphQL クエリに型を付与する方法を紹介したいと思います。
背景
TypeScript で GraphQL を扱う例として以下のようなコードを前提とします。
import React from 'react'; import { useQuery } from '@apollo/client'; import { gql } from '@apollo/client'; const GET_USER = gql` query GetUser($id: ID!) { user(id: $id) { id name email } } `; export const UserComponent: React.FC<{ userId: string }> = ({ userId }) => { const { data } = useQuery(GET_USER, { variables: { id: userId } }); return ( <div> <h1>{data?.user.name}</h1> <p>{data?.user.email}</p> </div> ); };
useQuery はこのまま使うとクエリパラメータや出力パラメータの型が any 型になってしまいます😰
any 型なので型安全ではなく、保守性に難がありこのままでは困りますよね。
graphql-codegen を使って型を自動生成するという手もありますが、そのためには codegen.ts 作成等のセットアップが必要です🤔
複数チームが並行開発するような大規模リポジトリの場合、一からセットアップするのは少々手間です。
まずは手っ取り早く型をつけたいけど、何かいい方法は無いか...と探したところ TypedDocumentNode に出会いました✨
TypedDocumentNode の使い方
定義した GraphQL クエリに対して、TypedDocumentNode で型情報をつけるだけです。
import React from 'react'; import { useQuery } from '@apollo/client'; import { gql, TypedDocumentNode } from '@apollo/client'; interface GetUserQuery { user: { id: string; name: string; email: string; }; } interface GetUserQueryVariables { id: string; } // クエリに TypedDocumentNode を付ける const GET_USER: TypedDocumentNode<GetUserQuery, GetUserQueryVariables> = gql` query GetUser($id: ID!) { user(id: $id) { id name email } } `; export const UserComponent: React.FC<{ userId: string }> = ({ userId }) => { const { data } = useQuery(GET_USER, { variables: { id: userId } }); return ( <div> <h1>{data?.user.name}</h1> <p>{data?.user.email}</p> </div> ); };
まとめ
TypedDocumentNode を使うことで、GraphQL クエリに簡単に型を付与することができます。graphql-codegen を使わずに、シンプルに型を付与したい場合には、ぜひお試しあれ。
余談ですが、先日初めてグランピングに行きました。テラスハウスに泊まったのですが、キャンプと違って全て準備されているのでとても気軽に行けました。
夕食(BBQ)が美味しくて最高だったんですが、グランピング施設に住み着いてる猫が人懐こくて最高すぎました。(たくさん触らせてもらいました)
弥生では一緒に働く仲間を募集しています。 herp.careers