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

如何让Urql(TypeScript)接受Vue响应式变量作为graphql-codegen查询参数

问题

在Vue项目中使用Urql和graphql-codegen时,Urql的useQuery()支持传入Vue响应式变量(如Ref),实现查询随变量更新自动响应,但graphql-codegen生成的变量参数类型要求为标量(如string),导致传入Ref时TypeScript报错。

当前codegen.ts配置:

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

const config: CodegenConfig = {
  schema: 'http://localhost:5001/graphql',
  documents: ['src/**/*.vue', 'src/**/*.ts'],
  ignoreNoDocuments: true, // 提升监听模式体验
  generates: {
    './src/gql/': {
      preset: 'client',
      config: {
        useTypeImports: true,
        scalars: {
          CustomDate: 'string',
          ObjectID: 'string',
        },
      },
      plugins: [],
    },
  },
};

export default config;

生成的变量类型示例:

export type Scalars = {
  String: string;
  ObjectID: string;
};

export type GetItemQueryVariables = Exact<{
  _id: Scalars['ObjectID'];
}>;

调用代码示例(报错行:variables: { _id: id },提示Ref<string>无法赋值给string):

const id = ref('123');

const queryResult = useQuery({
  query: queryGQL, // 对应get item的GraphQL查询
  variables: { _id: id },
});

不想通过泛型绕过类型检查,询问是否有graphql-codegen配置项解决该问题,或自动修补TypeScript定义的方法。


解决方案

1. 调整graphql-codegen配置,原生支持响应式变量类型

在codegen的config中添加maybeValue配置,让生成的变量类型同时兼容原始标量和Vue响应式类型:

修改后的codegen.ts配置:

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

const config: CodegenConfig = {
  schema: 'http://localhost:5001/graphql',
  documents: ['src/**/*.vue', 'src/**/*.ts'],
  ignoreNoDocuments: true,
  generates: {
    './src/gql/': {
      preset: 'client',
      config: {
        useTypeImports: true,
        scalars: {
          CustomDate: 'string',
          ObjectID: 'string',
        },
        // 让每个变量字段同时支持原始类型和Vue Ref类型
        maybeValue: 'T | import("vue").Ref<T>',
      },
      plugins: [],
    },
  },
};

export default config;

配置生效后,生成的GetItemQueryVariables中_id的类型会变为string | Ref<string>,完美匹配Urql对响应式变量的支持,无需修改业务代码。

2. 用TypeScript工具类型手动包装变量类型

如果不想改动codegen配置,可以自定义一个工具类型,将生成的变量类型自动转为兼容响应式的版本:

import type { Ref } from 'vue';

// 工具类型:将对象的每个字段转为「原始类型 | Ref<原始类型>」
type ReactiveVariables<T> = {
  [K in keyof T]: T[K] | Ref<T[K]>;
};

// 使用时指定泛型即可
const queryResult = useQuery<GetItemQuery, ReactiveVariables<GetItemQueryVariables>>({
  query: queryGQL,
  variables: { _id: id },
});

这种方式保留了类型检查的严谨性,同时兼容响应式变量,无需修改生成代码。

3. 自定义graphql-codegen插件(进阶)

如果需要更定制化的类型生成逻辑,可以编写一个简单的codegen插件,自动修改生成的变量类型,为每个字段添加Ref支持。不过前两种方法已经能覆盖绝大多数场景,仅在有特殊需求时才需要使用此方案。


内容的提问来源于stack exchange,提问作者Dov Rosenberg

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 10:05:23