【问题标题】:Union Types expecting other type when passed as props to component?联合类型在作为道具传递给组件时期望其他类型?
【发布时间】:2018-02-05 07:16:01
【问题描述】:

我正在使用带有 React 的 Typescript。

我正在从返回两种类型的 API 检索数据:VirtualMachineDisk。后端负责区分资源类型,根据查询结果返回两者的类型:

requestMoreInfo: (resourceType: string, resourceId: number): AppThunkAction<ResourceActions> => (dispatch, getState) => {
    let fetchResourceInfo = fetch('http://localhost:5004/GetResourceTypeInformation/' + resourceType + '/' + resourceId, {
        method: 'GET'
    })

我已经为我的 Redux 状态声明了一个联合类型:

export interface ResourceState {
    currentResourceInformation?: VirtualMachineInformation | DiskInformation;
}

我随后将响应转换为由传递给函数的资源类型确定的类型,并调度一个操作来更新我的组件状态。这就是我认为我错的地方。

if (resourceType == "Virtual Machine") {
  var vmResponse = response.json() as VirtualMachineInformation;

  dispatch({
    type: 'RECEIVE_RESOURCE_INFO',
    resourceInfo: vmResponse
  });
}
else if (resourceType == "Disk") {
  var diskResponse = response.json() as DiskInformation;
  dispatch({
    type: 'RECEIVE_RESOURCE_INFO',
    resourceInfo: diskResponse
  });
}

TypeScript 似乎对此很满意。但是,我随后尝试渲染子组件并将此更新状态作为道具传递:

private requestResourceInformation = (resourceType: string, resourceId: number) => {
    this.props.requestMoreInfo(resourceType, resourceId);

    if (resourceType == "Virtual Machine") {
        return <VirtualMachineResource virtualMachine={this.props.currentResourceInformation} />
    }
}

这只是用数据映射一个表。

但是,我正在检索错误:

  Type 'VirtualMachineInformation | DiskInformation | undefined' is not assignable to type 'VirtualMachineInformation | undefined'.
    Type 'DiskInformation' is not assignable to type 'VirtualMachineInformation | undefined'.
      Type 'DiskInformation' is not assignable to type 'VirtualMachineInformation'.
        Property 'azureVmId' is missing in type 'DiskInformation

我相信这是因为 TypeScript 仍然将该值视为联合类型,并且预期值存在于 VirtualMachine 类型中,但不存在于 Disk 类型中。

我在哪里做错了?检索数据后是否有明确的方法来声明联合的特定类型?

【问题讨论】:

  • 是的,这是可能的,您已经在代码中通过 as 关键字执行此操作 - 这称为类型转换或类型断言 - typescriptlang.org/docs/handbook/…
  • 您是否尝试将其投射到您将其分配给 VirtualMachineResource 的位置,例如 if (resourceType == "Virtual Machine") { const info = &lt;VirtualMachineInformation&gt;this.props.currentResourceInformation; return &lt;VirtualMachineResource virtualMachine={info} /&gt; }
  • @Roomy 这是我的假设,但是根据 Typescript 编译器,在渲染子组件时无法确定类型。
  • @dashton 这会起作用,但我认为这是.tsx,它将&lt;&gt;标签解释为JSX。也许这是我的问题。

标签: reactjs typescript redux react-redux


【解决方案1】:

virtualMachine 属性不接受 DiskInformation 接口作为值 - 这是你的问题。 TypeScript 编译器在编译时不知道该值的确切类型,因此猜测该类型是这三种类型之一:VirtualMachineInformationDiskInformationundefined

正如我在 cmets 部分中所写 - 您可以(至少)使用三种解决方案来解决您的问题:

  1. 使用类型断言 - https://www.typescriptlang.org/docs/handbook/basic-types.html#type-assertions - 你不能在 tsx 文件中使用 &lt;Type&gt;value 语法 return &lt;SomeComponent prop={value as Type}&gt;&lt;/SomeComponent&gt;

  2. 使用类型保护https://www.typescriptlang.org/docs/handbook/advanced-types.html#user-defined-type-guards

    if ([check if type of the value is the Type]) { return [something else] } [TypeScript knows that the value IS NOT an instance of the Type here] return <SomeComponent prop={value}></SomeComponent>

  3. 使用重载 - http://www.typescriptlang.org/docs/handbook/functions.html#overloads

    class X { private y(x: "abc"): "cda"; private y(x: "cda"): "abc"; private y(x: string): string { [method logic] } }

【讨论】:

  • 添加到这个 - 结果我没有做错任何事情,我只是在将道具传递给组件时没有正确地转换类型。类型断言专门解决了我的问题。只需在 TSX 文件中使用正确的上下文(as 而不是 &lt;type&gt;
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-19
  • 2019-01-24
  • 2020-03-22
相关资源
最近更新 更多