【问题标题】:typescript trouble in tuple town: preserving argument types元组镇的打字稿麻烦:保留参数类型
【发布时间】:2020-09-28 18:57:50
【问题描述】:

我很难弄清楚如何在这里创建我的and 函数:它的工作很简单。它必须接受一堆项目,并将它们连接成一个以"and"开头的数组

// the items 'and' may accept
type Item = false
  | {type: "alpha", a: boolean}
  | {type: "bravo", b: number}

// 'and' function adds items to an array
function and<Items extends Item[]>(
    ...items: Items
  ): ["and", ...Items] {

  return ["and", ...items]
}

// calling 'and' with a few items
const [op, item1, item2, item3] = and(
  false,
  {type: "alpha", a: true},
  {type: "bravo", b: 3.14},
)

// verifying the types are preserved
op    //> ✔ type "and"
item1 //> ✘ type Item, expected false
item2 //> ✘ type Item, expected {type: "alpha", a: true}
item3 //> ✘ type Item, expected {type: "bravo", b: 3.14}

问题是 item1、item2 和 item3 都丢失了它们原来的特定类型信息,因此我的 and 函数实际上是对类型的破坏性操作——相反,我需要保留类型

有不同的方法吗?谢谢!

【问题讨论】:

    标签: typescript


    【解决方案1】:

    确实,打字稿不太适合这种操作(反正我不知道)。

    问题似乎是在某些情况下编译器将无法正确键入这些人

    const whatsMyType: Item = false
    
    // calling 'and' with a few items
    const [op, item1] = and(
      whatsMyType
    )
    

    我会选择以下两种方法之一:

    重载

    优点:不费吹灰之力就能正确输入

    缺点:可扩展性不大

    (obs:例如RxJS pipe选择的方法)

    function and<A extends Item>(a: A): ['and', A];
    function and<A extends Item, B extends Item>(a: A, b: B): ['and', A, B];
    function and<A extends Item, B extends Item, C extends Item>(a: A, b: B, c: C): ['and', A, B, C];
    function and<Items extends Item[]>(
        ...items: Items
      ): ["and", ...Items] {
    
      return ["and", ...items]
    }
    

    类型谓词

    优点:可扩展

    缺点:代码中有额外的逻辑

    const isFalseItem = (a: Item): a is false => {return a === false};
    const isAlphaItem = (a: Item): a is ({type: "alpha", a: boolean}) => { return !isFalseItem(a) && a.type === 'alpha'}
    const isBravoItem = (a: Item): a is ({type: "bravo", b: number}) => { return !isFalseItem(a) && a.type === 'bravo'}
    
    const [op, item1, item2, item3] = and(
      false,
      {type: "alpha", a: true},
      {type: "bravo", b: 3.14},
    )
    
    if (isAlphaItem(item1)) {
     // do something alpha
    } else if (isBravoItem(item1)) {
     // do something bravo
    }
    

    【讨论】:

      猜你喜欢
      • 2011-08-20
      • 1970-01-01
      • 2019-03-22
      • 2020-05-25
      • 2020-05-11
      • 2018-05-02
      • 1970-01-01
      • 2012-02-24
      • 2019-03-23
      相关资源
      最近更新 更多