最近才深切地意识到 graphql-code-generator 的便利之处
首先
今天也是如往常一样,在开发一个前端使用React,后端使用Rails,同时配合API的单页应用。
我觉得在TypeScript的React中声明react-apollo的类型很繁琐。
由于后端使用了GraphQL,它似乎在很多地方都进行了类型声明,感觉有点微妙。。
让我们讨论使用graphql-code-generator来解决一些令人不适的问题。
本次的組成
前端
GitHub –> GitHub
-
- React(SPAで)
-
- TypeScript
-
- create-react-app
- React Apollo
后端
GitHub -> GitHub (GitHub)
-
- Ruby
-
- Rails(APIで)
- GraphQL
为了将上述的两个存储库与此存储库协同工作(作为开发环境),我们决定采用联动机制。
暂时跟随Apollo的官方指南试一试
我已经在后端创建了一个名为todos的API,该API可以获取Todo模型中的所有数据。
将其在前端获取并显示出来。
+import { gql, useQuery } from "@apollo/client";
import React from "react";
import logo from "./logo.svg";
import "./App.css";
+const TODOS_QUERY = gql`
+ query {
+ todos {
+ name
+ }
+ }
+`;
const App = () => {
+ const { loading, data } = useQuery(TODOS_QUERY);
+
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.tsx</code> and save to reload.
</p>
- <a
- className="App-link"
- href="https://reactjs.org"
- target="_blank"
- rel="noopener noreferrer"
- >
- Learn React
- </a>
+ {loading ? (
+ <p>Loading ...</p>
+ ) : (
+ <ul>
+ {data && data.todos.map(({ name }, i) => <li key={i}>{name}</li>)}
+ </ul>
+ )}
</header>
</div>
);
};
export default App;
因为没有进行类型声明,所以出现了错误。

我会给你类型声明。
所需的类型是Todo模型的类型和响应值的类型。
响应返回了{“data”:{“todos”: []}}这个值。
interface Todo {
name: string;
}
interface TodosData {
todos: Todo[];
}
以下是如何使用TodosData的方法。
- const { loading, data } = useQuery(TODOS_QUERY);
+ const { loading, data } = useQuery<TodosData>(TODOS_QUERY);
没有发生任何错误,执行成功。

我要试试如果安装了GraphQL Code Generator会发生什么。
使用GraphQL代码生成器
按照公式手册的步骤,进行安装和设置。
$ yarn add -D @graphql-codegen/cli @graphql-codegen/typescript @graphql-codegen/typescript-operations
"scripts": {
"generate": "graphql-codegen"
}
由于后端已经准备好了端点http://localhost:5000/graphql,所以我们将在schema中使用它。
schema: http://localhost:5000/graphql
documents: ./graphql/queries/*.graphql
generates:
./src/types.d.ts:
plugins:
- typescript
- typescript-operations
如果使用`documents`选项,似乎需要安装`@graphql-codegen/typescript-operations`。
将todos的查询内容写入到在documents指定的位置上。
query {
todos {
name
}
}
在启动后端的情况下,尝试执行预设的生成命令。
$ yarn generate
已创建src/types.d.ts文件。
...省略...
export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never; }>;
export type Unnamed_1_Query = (
{ __typename?: 'Query' }
& { todos: Array<(
{ __typename?: 'Todo' }
& Pick<Todo, 'name'>
)> }
);
由于未命名,我们给查询命名并重新执行。
-query {
+query todos {
todos {
name
}
}
在src/types.d.ts文件中定义了一个名为TodosQuery的类型。
我尝试将其用作useQuery的类型。
+ import { TodosQuery } from "./types.d";
- const { loading, data } = useQuery<TodosData>(TODOS_QUERY);
+ const { loading, data } = useQuery<TodosQuery>(TODOS_QUERY);
我能够确认它们的运作是相似的。

在 src/App.tsx 中,不再需要定义 Todo 模型的类型和响应值的类型。
然而,在src/App.tsx和graphql/queries/todos.graphql两个地方编写用于获取TODO数据的查询调用,感觉有点不好吧。
如果有一个专用的 useQuery 来获取 todos,就不需要传递类型和查询了…
引入@graphql-codegen/typescript-react-apollo。
如果有一个专门用于获取todos的useQuery函数,就不需要传递类型和查询了。。。
因此,我们将解除这种令人不悦的感觉。
首先要安装
$ yarn add -D @graphql-codegen/typescript-react-apollo
添加 typescript-react-apollo。
schema: http://localhost:5000/graphql
documents: ./graphql/queries/*.graphql
generates:
./src/types.d.ts:
plugins:
- typescript
- typescript-operations
+ - typescript-react-apollo
执行生成命令
$ yarn generate
我們將嘗試使用生成的useTodosQuery函數,它位於src/types.d.ts中。
- import { TodosQuery } from "./types.d";
+ import { useTodosQuery } from "./types.d";
- const { loading, data } = useQuery<TodosQuery>(TODOS_QUERY);
+ const { loading, data } = useTodosQuery();
运作得很好,不是吗?

GraphQL具有的方便之处是它可以仅获取需要的字段,即使是相同的API。
刚刚,在获取todos数据时,只指定并获取了name,并实现了类似于一览表的功能。
实现对其进行单独编辑和删除功能,除非name是唯一的,否则需要类似id的标识。
需要确定特定的任务。
如果在另一个屏幕或其他地方时,除了姓名之外,还需要身份证号,我就会想要创建以下类似的查询。
query todos {
todos {
id
name
}
}
然而,所有由graphql-code-generator生成的函数都设置成存放在src/types.d.ts中。
由于已经存在一个函数来获取仅指定name的todos的查询,所以请创建以下类似的文件:
运行yarn generate会出现“不是所有操作都有唯一的名称”的错误。
query todos {
todos {
id
name
}
}
请确认右侧查询中列出的名称必须是唯一的。
-query todos {
+query todosIncludeId {
todos {
id
name
}
}
我试着将查询的名称更改为独特的名称。
然后,除了在src/types.d.ts中生成useTodosQuery之外,还生成了一个名为useTodosIncludeIdQuery的函数。
你可以在不破坏GraphQL的有用特性的情况下使用它。
文献引用
-
- Apollo Docs
-
- Graphql Code Generator – getting-started
-
- graphql-codegen で型定義を生成する (React, Apollo, TypeScript) – Qiita
-
- GraphQL Code Generator の使い方。〜GraphQLのSchemaからTSの型定義を自動生成する〜 – Qiita
- Graphql Code Generator – typescript-react-apollo