打字稿细化混乱

时间:2020-09-20 07:42:04

标签: typescript union-types

我正在阅读《 编程打字稿》 。以下示例说明了优化,我对此感到困惑:

type UserTextEvent = { value: string; target: HTMLInputElement };
type UserMouseEvent = { value: [number, number]; target: HTMLElement };

type UserEvent = UserTextEvent | UserMouseEvent;

function handle(event: UserEvent) {
  if (typeof event.value === "string") {
    event.value; // string
    event.target; // HTMLInputElement | HTMLElement (1)
    // ...
    return;
  }
  event.value; // [number, number]
  event.target; // HTMLInputElement | HTMLElement (2)
}

我认为(1)和(2)中event.target的类型分别为 HTMLInputElement HTMLElement 。我的理解是,如果event.value的类型是确定的,则event.target的类型是确定的。但这是 HTMLInputElement | HTMLElement 。有人能比这本书更清楚地解释它吗?谢谢。

1 个答案:

答案 0 :(得分:1)

不幸的是,您只是在检查属性的类型,因此,打字稿将不会采用类类型。为此,您必须使用一种推断类型的方法来检查自己。

type UserTextEvent = { value: string; target: HTMLInputElement };
type UserMouseEvent = { value: [number, number]; target: HTMLElement };

type UserEvent = UserTextEvent | UserMouseEvent;

function isUserTextEvent(event: UserEvent): event is UserTextEvent {
  return typeof event.value === "string";
}

function handle(event: UserEvent) {
  if (isUserTextEvent(event)) {
    event.value; // string
    event.target; // HTMLInputElement  (1)
    // ...
    return;
  }
  event.value; // [number, number]
  event.target; // HTMLElement (2)
}

您可以在playground

上查看

验证时

typeof event.value === "string"

Typescript只能推断该值实际上是一个字符串,而在其他情况下只能是[number, number]

但是它不能推断valueHTMLInputElementHTMLElement,因此仍然考虑HTMLInputElement | HTMLElement。您需要使用一种方法来说实际上事件是UserTextEvent

相关问题