简体   繁体   English

Typescript 联合类型数组`a[] | b[]` 不是 `reduce`able,而是 `map`able

[英]Typescript union type array `a[] | b[]` is not `reduce`able, but `map`able

I'm trying to reduce over a union of array-types: foo[] | bar[]我正在尝试reduce数组类型的联合: foo[] | bar[] foo[] | bar[] . foo[] | bar[] With map it works as expected and I get an element of foo|bar in the lamda, but it does not work with reduce .使用map它可以按预期工作,并且我在 lamda 中获得了foo|bar的元素,但它不适用于reduce I get the error, that 'the expression is not callable, because the signatures are not compatible'.我收到错误消息,即“表达式不可调用,因为签名不兼容”。

Maybe this is related, but that was in TS 3.6 days, and I'm using 4.5.也许是相关的,但那是在 TS 3.6 天,我使用的是 4.5。 Is there a (neat) way around this?有没有解决这个问题的(整洁的)方法?

I have a Typescript Playground here这里有一个 Typescript 游乐场

const m = [] as Array<number | string>;
m.reduce((it) => it); // ok
m.map((it) => it); // ok

const m2 = [] as Array<number> | Array<string>;
m2.reduce((it) => it);
m2.reduce((it) => it as any);  // not even with 'any'-lambda
// This expression is not callable.
// Each member of the union type '<OMITTED> ...' has signatures, but none of those signatures are compatible with each other.
m2.map((it) => it); // why does `map` work then ?

// same with tuples
const m3 = [1, 1] as [number, number] | [string];
m3.map((it) => it);
m3.reduce((it) => it); // same error

In addition to jcalz comment I found the following.除了 jcalz 评论,我还发现了以下内容。

Typescript Definitions Typescript 定义

The function signature for map is map 的 function 签名是

export function map<T, U>(iterable: Iterable<T>, mapper: (value: T, index: number, iterable: Iterable<T>) => U): U[];

It has a different return type U then it's input T.它具有不同的返回类型 U,然后是输入 T。

One of the function signatures for reduce is用于减少的 function 签名之一

export function reduce<T>(
   iterable: Iterable<T>,
    reducer: (previousValue: T, currentValue: T, currentIndex: number, iterable: Iterable<T>) => T,
initialValue?: T
): T;

It has the same return type as it's input (T).它具有与输入 (T) 相同的返回类型。 The trouble comes when assigning the type back unto itself.当将类型重新分配给自身时,麻烦就来了。 Typescript doesn't (and shouldn't) know which type to use. Typescript 不(也不应该)知道使用哪种类型。

One solution is to type check before using reduce, with a type guard like so,一种解决方案是在使用 reduce 之前进行类型检查,使用这样的类型保护,

const isNumberArray = (arr: unknown[]): arr is number[] => {
  for (let i = 0; i < arr.length; i++) {
      const element = arr[i]

      if (typeof element !== 'number') {
          return false
      }
  }

  return true
}

Playground 操场

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM