首页 > 解决方案 > 为什么我的 TypeScript 报告联合类型的错误?

问题描述

我有:

type: 'WEBSOCKET' | 'HTTP_STREAM';
connection: WebSocketType | HTTPStreamType;

在哪里:

interface Header {
  key: string;
  val: string;
}

export interface WebSocketType {
  websocketUrl: string;
}

export interface HTTPStreamType {
  streamUrl: string;
  method: 'get' | 'put';
  headers: Header[];
}

我正在努力:

        if (newStream.type === 'WEBSOCKET') {
          if (newStream?.connection?.websocketUrl?.length > 0) {
            return setIsNextDisabled(false)
          }
        }

但我得到的错误是:

Property 'websocketUrl' does not exist on type 'WebSocketType | HTTPStreamType'.
  Property 'websocketUrl' does not exist on type 'HTTPStreamType'.

我以为这guard会起作用,但事实并非如此。

标签: typescripttypeguards

解决方案


我假设你有类似的东西:

interface MyData {
    type: 'WEBSOCKET' | 'HTTP_STREAM';
    connection: WebSocketType | HTTPStreamType;
}

根据这个界面,你可以拥有一个typeofWEBSOCKET和一个connectionof HTTPStreamType。你在任何地方都没有保证每个工会的成员之间有任何联系。type并且connection都可以是工会的任何一个成员。

这就是为什么打字稿认为你的警卫没有帮助。

相反,您需要一种不同的联合:

type MyData = {
    type: 'WEBSOCKET';
    connection: WebSocketType;
} | {
    type: 'HTTP_STREAM';
    connection: HTTPStreamType;
}

这种类型表示它MyData可能是一个WEBSOCKETWebSocketType连接的类型,HTTP_STREAM可能是一个有连接的类型HTTPStreamType。但它永远不能混合第一个属性和第二个属性。

现在打字稿可以推断出对其中一个属性的检查允许知道另一个属性类型。

带有通过类型检查的代码的游乐场。


通过一些重构,您可以避免重复像这样的常见属性。

interface MyCommonData {
    foo: string
    bar: number
}

interface WebSocketData extends MyCommonData {
    type: 'WEBSOCKET'
    connection: WebSocketType
}

interface HttpStreamData extends MyCommonData {
    type: 'HTTP_STREAM';
    connection: HTTPStreamType;
}

type MyData = WebSocketData | HttpStreamData

推荐阅读