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

如何用TypeScript泛型为动态生成的GraphQL查询实现正确类型

解决TypeScript识别动态生成GraphQL查询类型的问题

要让TypeScript同时识别默认查询和动态生成的查询属性,核心是通过泛型捕获数组中key的字面量类型,并基于此构造出动态属性的类型,再与默认查询类型合并。具体步骤如下:

1. 让数组的key成为字面量类型

调用generateQueries时,使用as const断言数组,让TypeScript捕获每个key的具体字面量值,而非宽泛的string类型:

const items = [{ key: 'test_1' }, { key: 'test_2' }] as const;
export const QUERIES = generateQueries(items);

2. 修改函数的泛型与返回类型

调整generateQueries函数,通过泛型提取数组中key的类型,构造动态属性的类型,并与默认查询类型合并:

import { gql, DocumentNode } from '@apollo/client';

const DEFAULT_QUERY_1 = gql`
  query DefaultQuery1 {
    defaultQuery1 {
      ...Response
    }
  }
`;

interface Item {
  key: string;
}

// 定义动态查询的类型构造器
type DynamicQueries<T extends readonly Item[]> = {
  [K in T[number]['key'] as `MY_DYNAMIC_${Uppercase<K>}`]: DocumentNode;
};

function generateQueries<T extends readonly Item[]>(items: T): typeof DEFAULT_QUERY_1 & DynamicQueries<T> {
  return {
    ...DEFAULT_QUERY_1,
    ...items.reduce((acc, { key }) => {
      return {
        ...acc,
        [`MY_DYNAMIC_${key.toUpperCase()}`]: gql`
          query MyDynamic${key} {
            myDynamic${key} {
              count
            }
          }
        `
      };
    }, {} as DynamicQueries<T>) // 断言累加器类型,避免TS推断为{}
  } as typeof DEFAULT_QUERY_1 & DynamicQueries<T>;
}

3. 组件中正常使用

此时TypeScript能正确识别动态生成的属性,不再报错:

import { useQuery } from "@apollo/client";
import { QUERIES } from "./queries";

function Comp() {
  const { data } = useQuery(QUERIES.MY_DYNAMIC_TEST_1); // 类型校验通过
  const { data: defaultData } = useQuery(QUERIES.DEFAULT_QUERY_1); // 默认查询也正常识别
}

关键原理说明

  • as const固定了数组元素的key为字面量类型,让TypeScript能静态分析出具体的key值;
  • 泛型T extends readonly Item[]捕获了数组的具体类型,T[number]['key']提取出所有key的字面量联合类型;
  • as MY_DYNAMIC_${Uppercase}``将每个key转换为对应的动态属性名,构造出动态查询的类型;
  • 通过类型交叉&将默认查询类型与动态查询类型合并,最终返回的类型包含所有属性。

内容的提问来源于stack exchange,提问作者Lionel T

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 02:15:03