【问题标题】:Infer a reduced union type by checking for property existence?通过检查属性是否存在来推断简化的联合类型?
【发布时间】:2018-01-11 12:42:57
【问题描述】:

我有一个非常大的联合类型,其成员有多种类型,并且有一些重叠。实际上,这些都是非常大的数据库模式中的各种类型的记录属性。

    type A = { x: number; y: number }
    type B = { y: number; z: number }
    // many many more types

    type All = 
        | A 
        | B
        // many many more types

我有一个非常通用的函数,它接受任何类型并根据某些属性的存在做一些事情。问题是我无法检查属性是否存在,因为 Typescript 会抛出错误,指出此联合中的某些类型没有该属性。但理想情况下,我可以检查是否存在,Typescript 会根据该属性的存在来推断类型...

    function f(value: All) {
        if (value.x) {
            // value must be A or anything that has an x property
        } else if (value.y) {
            // value must be B or anything that has an x property       
        }
    }

任何想法如何使这项工作?

【问题讨论】:

标签: typescript


【解决方案1】:

是的,您可以这样做:

type A = { x: number; y: number }
type B = { y: number; z: number }
type C = { z: number; x: number }
type D = { y: number; w: number }
type E = { w: number; z: number }
type All = A | B | C | D | E ;

function hasKey<K extends string>(key: K, val: any): val is {[P in K]: any} {
  return key in val;
}

function f(v: All) {
  if (hasKey('x', v)) {
    v // A | C
  } else if (hasKey('y',v)) {
    v // B | D
  } else {
    v // E
  }
}

hasKey 函数是一个用户定义的类型保护,它将为您缩小联合的范围。

【讨论】:

  • 哇,我永远不会发现这一点。是否有一个图书馆充满了这样的功能?必须有
【解决方案2】:

基于 jcalz 的回答,我更喜欢不需要专用库函数的方法:

type A = { x: number; y: number }
type B = { y: number; z: number }
type C = { z: number; x: number }
type D = { y: number; w: number }
type E = { w: number; z: number }
type All = A | B | C | D | E ;

function f(v: All) {
  if ('x' in v)) {
    v // A | C
  } else if ('y' in v)) {
    v // B | D
  } else {
    v // E
  }
}

我认为这种方法通过阅读更好地理解。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-11-25
    • 2019-08-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-26
    相关资源
    最近更新 更多