TypeScript无法解析GraphQL联合类型查询的类型问题求助
TypeScript联合类型访问专属属性报错问题
问题场景
我用GraphQL定义了FixedOrVariableCost联合类型,对应FixedCost和VariableCost两种类型,GraphQL Codegen生成了正确的联合类型定义,但在组件中访问联合类型的专属属性(比如fixedCostValue)时,TypeScript报错提示该属性不存在于联合类型的某一分支。
相关代码片段
Resolver定义:
@Query(() => FixedOrVariableCost, { name: 'oneCost' }) async getOneCost( @Args('id', { type: () => String }) id: MongooseSchema.Types.ObjectId ) { return this.costsService.getOneCost(id); }
联合类型定义:
const FixedOrVariableCost = createUnionType({ name: 'FixedOrVariableCost', types: () => [FixedCost, VariableCost] as const, });
生成的核心类型(简化后):
export type GetOneCostQuery = { oneCost: | { __typename?: 'FixedCost'; fixedCostValue: { amount: number; currency: unknown } } | { __typename?: 'VariableCost'; variableCostValue: number }; };
组件中报错的代码:
type OneCost = GetOneCostQuery['oneCost']; export const MyComponent = ({ cost }: { cost: OneCost }) => { console.log(cost.fixedCostValue); // TypeScript报错:属性'fixedCostValue'不存在于VariableCost类型上 return null; };
报错信息
La propriété 'fixedCostValue' n'existe pas sur le type '{ __typename?: "FixedCost" | undefined; ... fixedCostValue: { ...; }; } | { ...; }'. La propriété 'fixedCostValue' n'existe pas sur le type '{ __typename?: "VariableCost" | undefined; ... }'.ts(2339)
原因分析
TypeScript的联合类型要求访问的属性必须存在于联合类型的所有分支,否则会触发类型检查错误。fixedCostValue只属于FixedCost分支,VariableCost没有这个属性,所以直接访问会报错。
解决方案
1. 使用__typename类型守卫(推荐)
GraphQL会自动返回__typename字段(生成的类型已包含该字段),可以用它做类型窄化,让TypeScript自动推断当前分支的具体类型:
export const MyComponent = ({ cost }: { cost: OneCost }) => { if (cost.__typename === 'FixedCost') { // 此处TypeScript自动将cost推断为FixedCost类型 console.log(cost.fixedCostValue.amount); } else if (cost.__typename === 'VariableCost') { console.log(cost.variableCostValue); } return null; };
2. 自定义类型守卫函数
如果不想依赖__typename,可以编写自定义类型守卫函数来判断类型:
function isFixedCost(cost: OneCost): cost is Extract<OneCost, { fixedCostValue: unknown }> { return 'fixedCostValue' in cost; } export const MyComponent = ({ cost }: { cost: OneCost }) => { if (isFixedCost(cost)) { console.log(cost.fixedCostValue); } else { console.log(cost.variableCostValue); } return null; };
3. 可选链+类型断言(临时方案)
如果能确定当前cost是FixedCost类型,可临时用可选链避免运行时错误,或用类型断言跳过检查,但不推荐在类型不确定时使用:
export const MyComponent = ({ cost }: { cost: OneCost }) => { // 类型断言(仅确定类型时使用) console.log((cost as { fixedCostValue: unknown }).fixedCostValue); // 可选链(避免运行时报错) console.log(cost.fixedCostValue?.amount); return null; };
内容的提问来源于stack exchange,提问作者LIIT
相关产品推荐
相关产品推荐

