如何让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
相关产品推荐
相关产品推荐

