使用TypeScript和graphql-codegen工具,可以将模式(Schema)的类型定义和操作的类型定义分开生成

在本文中,我们将介绍如何使用graphql-codegen分别生成模式类型定义和操作类型定义的方法来生成TypeScript类型定义。

我会通过示例来说明实现上述内容的重要性,并展示使用import-types的方法。

准备生成源代码

首先,你需要准备下面的代码来生成元素:

    1. schema.gql: GraphQL的模式文件

 

    queries.gql: 描述操作的文件

每个内容如下:

scalar DateTime

type BlogPost {
  id: ID!
  title: String!
  description: String
  body: String!
  author: Author!
  createdOn: DateTime!
}

type Author {
  id: ID!
  name: String!
  email: String!
}

type Query {
  allBlogPosts: [BlogPost!]!
  blogPost(id: ID!): BlogPost
}

type Mutation {
  createBlogPost(input: CreateBlogPostInput): BlogPost
}

input CreateBlogPostInput {
  title: String!
  description: String
  body: String!
  authorId: ID!
}
query GetBlogPost($id: ID!) {
  blogPost(id: $id) {
    id
    title
    description
    author {
      id
      name
    }
    createdOn
  }
}

使用graphql-codegen在这里生成两个TypeScript的类型定义文件。

引入必要的工具

安装GraphQL Codegen和其他必要的工具来生成TypeScript类型文件。

yarn add graphql

yarn add -D typescript \
  @graphql-codegen/cli \
  @graphql-codegen/import-types-preset \
  @graphql-codegen/typescript \
  @graphql-codegen/typescript-operations \
  prettier

其中,@graphql-codegen/import-types-preset是重要的。安装它可以将生成的模式和操作的类型定义分别放入不同的文件中。

GraphQL Codegen的配置方式。

接下来我们将设置graphql-codegen。创建codegen.yml文件,并内容如下:

overwrite: true
schema: "./schema.gql"
documents:
  - queries.gql
generates:
  # スキーマの型定義
  types.ts: # [*1]
    plugins:
      - typescript
    config:
      scalars:
        DateTime: Date
    hooks:
      afterOneFileWrite:
        - prettier --write

  # 操作の型定義
  operations.ts:
    preset: import-types
    presetConfig:
      typesPath: ./types # [*1]から拡張子tsを除いたファイル名を指定します
    plugins:
      - typescript-operations
    hooks:
      afterOneFileWrite:
        - prettier --write

当使用这个配置来运行graphql-codegen时,将会生成两个文件:

    • types.ts

 

    operations.ts

每一个的内容如下所示:

export type Maybe<T> = T | null;
export type Exact<T extends { [key: string]: unknown }> = {
  [K in keyof T]: T[K];
};
export type MakeOptional<T, K extends keyof T> = Omit<T, K> &
  { [SubKey in K]?: Maybe<T[SubKey]> };
export type MakeMaybe<T, K extends keyof T> = Omit<T, K> &
  { [SubKey in K]: Maybe<T[SubKey]> };
/** All built-in and custom scalars, mapped to their actual values */
export type Scalars = {
  ID: string;
  String: string;
  Boolean: boolean;
  Int: number;
  Float: number;
  DateTime: Date;
};

export type Author = {
  __typename?: "Author";
  id: Scalars["ID"];
  name: Scalars["String"];
  email: Scalars["String"];
};

export type BlogPost = {
  __typename?: "BlogPost";
  id: Scalars["ID"];
  title: Scalars["String"];
  description?: Maybe<Scalars["String"]>;
  body: Scalars["String"];
  author: Author;
  createdOn: Scalars["DateTime"];
};

export type CreateBlogPostInput = {
  title: Scalars["String"];
  description?: Maybe<Scalars["String"]>;
  body: Scalars["String"];
  authorId: Scalars["ID"];
};

export type Mutation = {
  __typename?: "Mutation";
  createBlogPost?: Maybe<BlogPost>;
};

export type MutationCreateBlogPostArgs = {
  input?: Maybe<CreateBlogPostInput>;
};

export type Query = {
  __typename?: "Query";
  allBlogPosts: Array<BlogPost>;
  blogPost?: Maybe<BlogPost>;
};

export type QueryBlogPostArgs = {
  id: Scalars["ID"];
};
import * as Types from "./types";

export type GetBlogPostQueryVariables = Types.Exact<{
  id: Types.Scalars["ID"];
}>;

export type GetBlogPostQuery = { __typename?: "Query" } & {
  blogPost?: Types.Maybe<
    { __typename?: "BlogPost" } & Pick<
      Types.BlogPost,
      "id" | "title" | "description" | "createdOn"
    > & {
        author: { __typename?: "Author" } & Pick<Types.Author, "id" | "name">;
      }
  >;
};

根据您所看到的,operations.ts使用了types.ts中的类型进行导入和使用。

结束

这个例子中展示的代码可以在 GitHub 上找到,供您参考:
https://github.com/suinplayground/graphql-codegen-split-types-and-operation

广告
将在 10 秒后关闭
bannerAds