You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过@graphql-codegen/cli生成GraphQL查询的NodeType类型?

问题描述

我编写了如下GraphQL查询:

export const GET_ALL_ADVERT_CUSTOM_FIELD = gql(`
  query advertCustomFields {
    advertCustomFields {
      nodes {
        slug
        valueType
        displayName
        description
        canRead
      }
    }
  }
`)

我希望在React组件中获取过滤后的nodes列表:

import { Props as SelectProps } from 'react-select'
import React, { FC, useState } from 'react'
import ObjectSelector from 'components/Common/ObjectSelector'
import OptionWithDescription from './OptionWithDescription'
import { useQuery } from '@apollo/client'
import { AdvertCustomFieldsDocument } from '__generated__/graphql'

export const AdvertCustomFieldSelector: FC<SelectProps> = (props) => {
  const [data, setData] = useState<NodeType[]>()
  useQuery(AdvertCustomFieldsDocument, {
    onCompleted: (res) => {
      const filterData = res.advertCustomFields?.nodes?.filter((e) => e.canRead)
      setData(filterData)
    },
  })

  return (
    <ObjectSelector<Node>
      name={props.name}
      onChange={props.onChange}
      options={data as any}
      getOptionLabel={(option) => option?.displayName as string}
      getOptionValue={(option) => `${option.slug}`}
      components={{ Option: OptionWithDescription }}
    />
  )
}

当前问题是@graphql-codegen/cli未导出NodeType类型,我的codegen配置如下:

import { CodegenConfig } from '@graphql-codegen/cli'

const config: CodegenConfig = {
  schema: './app/graphql/schema.graphql',
  documents: ['./facerberus/components/**/*.ts'],
  ignoreNoDocuments: true, // for better experience with the watcher
  generates: {
    './facerberus/__generated__/': {
      preset: 'client',
      plugins: [],
      presetConfig: {
        gqlTagName: 'gql',
      },
    },
  },
}

export default config

请问需要调整哪些配置让codegen导出NodeType类型,或如何通过TypeScript实现该需求?


解决方案

方法一:调整Codegen配置生成显式类型

通过添加typescript和typescript-operations插件,并开启相关配置,让codegen导出更明确的子类型:

import { CodegenConfig } from '@graphql-codegen/cli'

const config: CodegenConfig = {
  schema: './app/graphql/schema.graphql',
  documents: ['./facerberus/components/**/*.ts'],
  ignoreNoDocuments: true,
  generates: {
    './facerberus/__generated__/': {
      preset: 'client',
      plugins: ['typescript', 'typescript-operations'],
      presetConfig: {
        gqlTagName: 'gql',
        // 开启导出子类型,确保节点类型被单独导出
        exportFragmentSpreadSubTypes: true,
        // 可选:导出所有生成的类型
        exportAllTypes: true
      },
      config: {
        skipTypename: false,
        enumsAsTypes: true
      }
    },
  },
}

export default config

重新运行codegen后,你可以在__generated__/graphql.ts中找到对应节点的类型(比如命名为AdvertCustomFieldsAdvertCustomFieldsNodes或根据schema定义的名称),直接导入使用:

import { AdvertCustomFieldsAdvertCustomFieldsNodes as NodeType } from '__generated__/graphql'

方法二:从查询结果类型中提取节点类型

如果不想修改配置,可直接通过TypeScript的类型推导从生成的查询类型中提取节点类型:

import { AdvertCustomFieldsQuery } from '__generated__/graphql'

// 提取nodes数组的元素类型
type NodeType = NonNullable<NonNullable<AdvertCustomFieldsQuery['advertCustomFields']>['nodes']>[number]

export const AdvertCustomFieldSelector: FC<SelectProps> = (props) => {
  const [data, setData] = useState<NodeType[]>()
  // 其余代码保持不变
}

这种方式无需修改codegen配置,直接利用类型推导获取目标类型,避免了any类型断言。

额外提示

  • 检查你的GraphQL Schema,如果advertCustomFields返回的节点类型是AdvertCustomField,codegen会自动生成同名类型,可直接导入使用。
  • 运行codegen时添加--watch参数,修改查询或Schema后自动更新生成的类型文件。

内容的提问来源于stack exchange,提问作者Trung Modern Coding

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 05:20:22