首页 > 解决方案 > 区分联合类型

问题描述

为什么我不能仅通过成员 x 是字符串而不是数字的信息来区分该联合?为什么我必须使用文字类型?

type A = { x: string ; y: string }
type B = { x: number ; y: number }
type C = A | B

function fn(p: C) {
  if (typeof p.x === 'string') { 
    // Typescript is unable to infer p as A
    // Typescript infer p.y as (string | number), why not just string ?
  }
  // Typescript is capable of inferring p.x as number - good
  // But cannot infer p.y as number, why ?
}

对我来说,这是不可能用像 {x:string,y:number} 这样的类型调用函数的,那么为什么打字稿假设这是可能的呢?

标签: typescripttypesdiscriminated-union

解决方案


不是直接解释为什么 Typescript 编译器无法通过 区分联合类型typeof,但手册说:

有以下三种成分:

  1. 具有共同的单例类型属性的类型——判别式。
  2. 一个类型别名,它接受这些类型的联合——联合。
  3. 在公共财产上键入警卫。

因此,为了缩小正确的类型,需要一个单例类型属性。我会使用自定义类型保护:

type A = { x: string ; y: string }
type B = { x: number ; y: number }
type C = A | B

function isA(obj: C): obj is A { 
  return typeof obj.x === 'string';
}

function isB(obj: C): obj is B { 
  return typeof obj.x === 'number';
}

function fn(p: C) {

  if (isA(p)) {
    // ...
  }

  if (isB(p)) {
    // ...
  }

}

推荐阅读