如何像apollo-client那样全局处理GraphQL联合类型解决TypeScript报错
解决方案
核心原因:Apollo Client默认会自动在所有查询的对象类型中插入__typename字段,配合graphql-codegen的Apollo相关插件会自动处理联合类型的类型窄化,而graphql-request默认不会做这个处理,所以才会出现类型报错。
你可以通过以下几步实现类似Apollo的全局处理,无需重复手写类型判断:
1. 配置graphql-codegen自动插入__typename并生成类型守卫
更新你的codegen.yml配置,启用自动插入__typename和类型守卫生成能力:
schema: ./schema.graphql documents: ./src/**/*.graphql generates: ./src/generated/graphql.ts: plugins: - typescript - typescript-operations - typescript-react-query - typescript-type-guards # 自动生成所有联合类型、接口的类型守卫函数 config: addTypename: true # 自动给所有查询的对象添加__typename字段 omitOperationSuffix: true reactQueryVersion: 4 # 匹配你实际使用的react-query版本
安装缺失的依赖:
npm i -D @graphql-codegen/typescript-type-guards
2. 全局封装graphql-request自动适配类型
封装全局的graphql-request实例,配合codegen自动生成的Sdk,所有请求的返回值会自动携带正确的窄化类型:
import { GraphQLClient } from 'graphql-request'; import { getSdk } from './generated/graphql'; const client = new GraphQLClient('/api/graphql', { headers: { // 你的全局请求头配置 } }); // 所有业务请求统一使用这个sdk调用,返回值类型已自动处理 export const gqlSdk = getSdk(client);
3. 自动生成的类型守卫使用(仅特殊场景需要)
如果遇到需要手动区分联合类型的场景,直接调用codegen生成的类型守卫函数即可,无需自己实现判断逻辑:
import { isImage, isEmoji } from './generated/graphql'; if (isImage(object.logo)) { // 此处TS会自动识别object.logo为Image类型,可直接访问url字段 console.log(object.logo.url); } else { // 此处TS会自动识别object.logo为Emoji类型 console.log(object.logo.emoji); }
免判断特殊配置(不推荐,会丢失类型安全)
如果你确定业务中所有Media类型的Image字段一定存在,可以在codegen中配置自定义类型映射跳过类型判断:
config: mappers: Media: '{ __typename: "Image" } & Omit<Image, "__typename"> | { __typename: "Emoji" } & Omit<Emoji, "__typename">'
内容的提问来源于stack exchange,提问作者Kam
相关产品推荐
相关产品推荐

