網站搜尋

程式碼生成 - 從 GraphQL 架構生成的 Typescript 類型中覆寫


我正在使用 graphql-code-generator 從我的 GraphQL 架構生成 TypeScript 類型。在 GraphQL 中,你可以創建自定義標量類型,這將生成以下類型:/graphql.ts

export type Scalars = {
  String: string;
  Boolean: boolean;
  NodeDescription: any;
};

export type CodeResource = {
  ast: Scalars["NodeDescription"];
};

如您所見,GraphQL 的預設標量類型如 String、Boolean 等,將對應到相應的 Typescript 類型。自訂標量類型如 NodeDescription 將獲得 Typescript 類型 any。

在我的 Angular 客戶端中,已經有一個 NodeDescription 類型(位於 ../app/shared/syntaxtree),我希望使用它來替代生成的 any 類型。有沒有辦法覆寫 Scalars 類型中的 NodeDescription 欄位?所以最終我希望生成的 CodeResource 類型中的 ast 欄位擁有 NodeDescription 類型,而不是 any。

我最初的想法是將 Scalars["NodeDescription"] 類型覆蓋為 NodeDescription。所以我嘗試在一個新文件中導入所有類型並像這樣覆蓋它們:/types.ts

import {Scalars} from "./graphql";
import {NodeDescription} from "../app/shared/syntaxtree";
type Overwrite<T, U> = Pick<T, Exclude<keyof T, keyof U>> & U;
type Scalar = Overwrite<Scalars, {NodeDescription: NodeDescription}>

這實際上是可行的,但 CodeResource 類型的 ast 欄位仍然是 any 類型。

另一個想法是使用一個搭配精心設計的 sed 命令的 bash 腳本,這樣生成的文件就會被編輯成如下形式:

import {NodeDescription} from "../app/shared/syntaxtree";
export type Scalars = {
  String: string;
  Boolean: boolean;
  NodeDescription: NodeDescription;
};

不過在我實施那種方法之前,我想知道是否有一個聰明的 TypeScript 方式來覆寫生成的類型。感謝幫助。

答案#1

我找到了一個特定的解決方案,如果你在使用 graphql-code-generator 時遇到相同的問題。有一個叫做 add 的插件。因此在 codegen.yml 中,你可以添加 imports 並處理自定義的 scalar 類型。我的 codegen.yml 現在看起來是這樣的:

overwrite: true
schema: "../schema/graphql/schema.json"
documents: "../schema/graphql/**/*.graphql"
generates:
  src/generated/graphql.ts:
    plugins:
      - "typescript"
      - "typescript-operations"
      - "typescript-apollo-angular"
      - add:
          content: 'import { NodeDescription } from "../app/shared/syntaxtree";'
    config:
      enumsAsTypes: true
      scalars:
        NodeDescription: NodeDescription
        ISO8601DateTime: string