← 中文资源

简体中文版本

GraphQL Codegen 类型化文档节点

用 graphql-codegen 产出类型化的文档节点:查询、变量与结果形状由 schema 推断,字段拼写错误在编译期即暴露。

阅读英文原文

示例说明

手写 GraphQL 查询的字符串与结果类型之间没有任何联系,拼错字段名要等运行时才知道。codegen 的 typedDocumentNode 模式把查询模板转换成带完整类型的对象:变量类型来自 schema 的参数定义,结果类型来自选择集精确推导——选了 rank 与 player.name,data 的形状就只有这些字段,加删字段立即引发类型错误。

技术要点

  • graphql 标签函数返回类型化文档节点
  • 变量与结果类型都由 schema 推断
  • 字段变更通过编译错误及时传导

代码解读

LeaderboardQuery 通过生成的 graphql 标签函数构造;组件把 region 受限为两个字面量之一,variables 的合法性由变量类型约束。useQuery 消费类型化节点后 data 自动窄化,leaderboard 数组的元素类型精确到选择集。fetchPolicy 固定缓存优先策略。

使用建议

生成文件提交或按需生成二选一并保持一致。schema 变更后立即重新生成,让破坏性改动在编译期拦截。选择集克制,只取渲染必需字段。

代码示例

import { useQuery } from '@apollo/client';
import { graphql } from '../generated/gql';

// 代码生成物由 graphql-codegen 从 schema 产出:
// const LeaderboardQuery = graphql(`
//   query Leaderboard($region: Region!) {
//     leaderboard(region: $region) {
//       rank
//       player { name }
//       score
//     }
//   }
// `);

const LeaderboardQuery = graphql(`
  query Leaderboard($region: Region!) {
    leaderboard(region: $region) {
      rank
      player { name }
      score
    }
  }
`);

function Leaderboard({ region }: { region: 'eu' | 'na' }) {
  const { data, loading, error } = useQuery(LeaderboardQuery, {
    variables: { region },
    fetchPolicy: 'cache-first',
  });

  if (loading) return <p>loading…</p>;
  if (error) return <p role="alert">failed to load leaderboard</p>;

  return (
    <ol>
      {data?.leaderboard.map((row) => (
        <li key={row.rank}>
          {row.player.name} — {row.score}
        </li>
      ))}
    </ol>
  );
}