具有联合类型和元组的传播算子

时间:2018-10-11 18:16:56

标签: typescript

我有一个密钥,可以是number类型,也可以是[number]类型,也可以是[number, number]类型;

我分别为每个类型和一个union type创建了一个类型,

type Foo    = [number, number?];
type Bar    = number;
type FooBar = Foo | Bar;

然后我写了一个比较方法,可以分析其中两个键。

我的问题是,我想限制比较,以便两个参数必须是同一类型。 IE比较FooFooBarBar,但不比较FooBar

如果我按如下方法进行比较:

compare(key1: FooBar, key2: FooBar)

然后它将接受这种未命中的比较:compare([1], 1)

如果我这样定义更多类型:

type FooFoo = [Foo, Foo];
type BarBar = [Bar, Bar];

并将比较签名更改为:

compare(keys: FooFoo|BarBar)

它将正确地将两个键限制为相同类型,但这意味着您必须将compare参数作为数组传递,这很丑陋。因此,我决定尝试使用传播运算符...

compare(...keys: FooFoo|BarBar)

但是它返回一个错误,指出FooFoo需要是一个数组。如果我使用compare(...keys: FooFoo),它不会抱怨(但仅限于FooFoo)。而且,如果我使用compare(...keys: BarBar),它也不会抱怨(但仅限于BarBar)。

有什么方法可以正确重载此方法,使其等同于:

//an example of what I want.
//Using Java or C#'s overloading style for illustration

function compare(k1: Bar, k2: Bar): boolean {
   return compare([key1], [key2]);
}

function compare(k1: Foo, k2: Foo): boolean {
  if (k1 === k2) { return true; }
  if (Array.isArray(k1) && Array.isArray(k2)) {
      return k1[0] === k2[0] && (k1[1] === k2[1] ||
        (!isSet(k1[1]) && !isSet(k2[1])));
  }
  return false;
}

//this would result in allowing and not allowing the following:
compare(1, 2); //valid
compare([1], [2]); //valid
compare([1, 2], [3, 4]); //valid
compare([1, 2], [3]); //valid
compare([1], [2, 3]); //valid

compare([1], 2); //not valid
compare([1, 2], 3); //not valid
compare(1, [2]); //not valid
compare(1, [2, 3]); //not valid

我已经设置好所有内容的stackblitz example。我希望我能做的是可能的。感谢您的任何建议。

1 个答案:

答案 0 :(得分:0)

这是Typescript 3.1版中的fixed(感谢jcalz)

要解决较早版本的问题,可以使用TypeScript重载。 (感谢SLaks)。 使用TypeScript重载时的注意事项:您必须为每个重载创建一个签名,并为所有重载提供支持的通用签名。 See here。最初,这让我有些不适,所以我认为值得重复。