reactjs - typescript 无法解析返回联合类型的 graphql 查询的输入

标签 reactjs typescript graphql react-query graphql-codegen

我想了解这里发生了什么,并且由于我对 typescript 不太有经验,因此我们将不胜感激任何帮助!

我有一个解析器可以从数据库返回一项成本:

  @Query(() => FixedOrVariableCost, { name: 'oneCost' })
  async getOneCost(
    @Args('id', { type: () => String }) id: MongooseSchema.Types.ObjectId
  ) {
    return this.costsService.getOneCost(id);
  }

它的返回类型FixedOrVariableCost是一个联合类型:

const FixedOrVariableCost = createUnionType({
  name: 'FixedOrVariableCost',
  types: () => [FixedCost, VariableCost] as const,
});

基本上在我的模型中,成本是固定的或可变的。 Cost 是我的 graphql 层中的一个抽象接口(interface)。

生成的架构:

union FixedOrVariableCost = FixedCost | VariableCost

oneCost(id: String!): FixedOrVariableCost!

这是我正在使用的查询:

const useGetOneCost = (id: string) =>
  useQuery(['getOneCost', id], async () => {
    return (
      graphQLClient.request(
        gql`
          query GetOneCost($id: String!) {
            oneCost(id: $id) {
              ... on Cost {
                _id
                kind
                code
                label
                title
                content
                costType {
                  _id
                  code
                  label
                }
                costMargin {
                  _id
                  code
                  label
                }
                createdAt
                createdBy {
                  _id
                }
                updatedAt
                updatedBy {
                  _id
                }
                status {
                  _id
                  code
                  label
                  color
                }
              }
              ... on FixedCost {
                fixedCostValue {
                  amount
                  currency {
                    _id
                    code
                    label
                    symbol
                  }
                }
              }
              ... on VariableCost {
                variableCostValue
              }
            }
          }
        `,
        { id }
      ),
      {
        enabled: !!id,
      }
    );
  });

graphql codegen 生成的类型如下:

export type GetOneCostQuery = {
  __typename?: 'Query';
  oneCost:
    | {
        __typename?: 'FixedCost';
        _id: string;
        kind: CostKind;
        code: string;
        label: string;
        title?: string | null;
        content?: string | null;
        createdAt: any;
        updatedAt: any;
        costType: {
          __typename?: 'CostType';
          _id: string;
          code: string;
          label: string;
        };
        costMargin: {
          __typename?: 'CostMargin';
          _id: string;
          code: string;
          label: string;
        };
        createdBy: { __typename?: 'User'; _id: string };
        updatedBy: { __typename?: 'User'; _id: string };
        status: {
          __typename?: 'GenericStatus';
          _id: string;
          code: string;
          label: string;
          color: string;
        };
        fixedCostValue: {
          __typename?: 'FixedCostValue';
          amount: number;
          currency: {
            __typename?: 'Currency';
            _id: string;
            code: string;
            label: string;
            symbol: string;
          };
        };
      }
    | {
        __typename?: 'VariableCost';
        _id: string;
        kind: CostKind;
        code: string;
        label: string;
        title?: string | null;
        content?: string | null;
        createdAt: any;
        updatedAt: any;
        variableCostValue: number;
        costType: {
          __typename?: 'CostType';
          _id: string;
          code: string;
          label: string;
        };
        costMargin: {
          __typename?: 'CostMargin';
          _id: string;
          code: string;
          label: string;
        };
        createdBy: { __typename?: 'User'; _id: string };
        updatedBy: { __typename?: 'User'; _id: string };
        status: {
          __typename?: 'GenericStatus';
          _id: string;
          code: string;
          label: string;
          color: string;
        };
      };
};

非常好!打字生成按预期工作

现在,我的一个组件接收成本作为 Prop ,因此我在 GetOneCostQuery 类型中选择 oneCost

type PropType<TObj, TProp extends keyof TObj> = TObj[TProp];

type OneCost = PropType<GetOneCostQuery, 'oneCost'>;

type Props = {
  cost: OneCost;
};

export const MyComponent = ({
  cost
}: Props) => {
  console.log(cost.fixedCostValue);
  return null;
}

``fixedCostValue 上的 ts 错误:

La propriété 'fixedCostValue' n'existe pas sur le type '{ __typename?: "FixedCost" | undefined; _id: string; kind: CostKind; code: string; label: string; title?: string | null | undefined; content?: string | null | undefined; createdAt: any; ... 6 more ...; fixedCostValue: { ...; }; } | { ...; }'.
  La propriété 'fixedCostValue' n'existe pas sur le type '{ __typename?: "VariableCost" | undefined; _id: string; kind: CostKind; code: string; label: string; title?: string | null | undefined; content?: string | null | undefined; createdAt: any; ... 6 more ...; status: { ...; }; }'.ts(2339)

大致用英语:“blablabla 类型上不存在属性‘fixedCostValue’”

如果成本是固定的,这个值也许不应该可用吗?为什么 typescript 无法识别这个值?这让我很困惑...

感谢您的帮助

最佳答案

Type OneCost 是一个联合,这意味着它是两个对象之一 - FixedCostVariableCost。 虽然第一个包含名为 fixedCostValue 的属性,但第二个不包含,因此会出现错误。

如果您检查对象中是否存在此属性,它就会通过。例如:

export const MyComponent = ({
  cost
}: Props) => {
  if ("fixedCostValue" in cost) {
    console.log(cost.fixedCostValue);
  };
  return null;
}

关于reactjs - typescript 无法解析返回联合类型的 graphql 查询的输入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73655559/

相关文章:

typescript - 使用reduce从对象数组创建强类型TS字典

node.js - NodeJS + EJS + Promise : page is not displayed until the promise is fulfilled

typescript - 如何删除 typescript 定义?

java - 为什么 Retrofit GraphQL 查询失败并出现意外字符 'M' 预期 '}' ?

reactjs - 使用 apollo 和 graphql 上传大于 16 kb 的文件时会损坏

reactjs - React Redux Router 传递 props

javascript - React/Jest/Enzyme 浅渲染测试中如何将文本输入到表单中?

reactjs - React Material-UI网格系统

reactjs - 突变后失去选择

reactjs - GraphQl 和条件解析器 API 请求