递归数组类型打字稿

时间:2018-08-02 15:57:10

标签: typescript

说我有类型 type Atom = string | boolean | number。我想定义一种数组类型,如:

NestedArray = Atom | [a_0, a_1, ... , a_n],其中每个a_iAtomNestedArray

这可以在Typescript中实现吗?

2 个答案:

答案 0 :(得分:7)

类型别名无法引用自身,因此这种简单的方法将失败:

type NestedArray = Atom | Array<NestedArray | Atom> //Type alias 'NestedArray' circularly references itself.

接口可以引用自身:

interface NestedArray extends Array<NestedArray | Atom> {

}

我们可以在顶层定义一个额外的并集来处理根本情况:

type Atom = string | boolean | number

interface NestedArray extends Array<NestedArray | Atom> {

}

type AtomOrArray = Atom | NestedArray;

//Usage
let foo: AtomOrArray = [
    "",
    1, 
    [1, 2, ""]
]   

let bar: AtomOrArray =  ""

答案 1 :(得分:0)

现在打字稿允许类型循环引用自身,例如:

type RArray = (string | RArray)[];

如果要在递归函数中定义泛型类型,可以使用interface ...<T> extends (T|...<T>)[]

interface RA<T> extends Array<T | RA<T>> { }

例如,创建一个函数来递归求和

function sum(arr: RA<number>) {
  let res = 0;
  arr.forEach((n) => {
    if (Array.isArray(n)) {
      res += sum(n);
    } else {
      res += n;
    }
  });
  return res;
}
console.log(sum([1, 2, 3, [4, [5]], [[6]]]))
// output: 21

但是这种方式有一些缺点,编译器无法知道n的具体类型

arr.forEach((n) => {
    if (Array.isArray(n)) { // typeof n: `number | RA<number>`
      res += sum(n);
    } else {
      res += n;
    }
  });