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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 06:45:35