簡體   English   中英

遞歸數組類型打字稿

[英]Recursive array type typescript

假設我有類型type Atom = string | boolean | number type Atom = string | boolean | number type Atom = string | boolean | number 我想定義一種類型的數組,如:

NestedArray = Atom | [a_0, a_1, ... , a_n] NestedArray = Atom | [a_0, a_1, ... , a_n]其中每個a_i是一個Atom或一個NestedArray

這可以在打字稿中實現嗎?

類型別名不能引用自己,所以這種幼稚的方法會失敗:

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 =  ""

現在打字稿允許類型循環引用自身,例如:

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;
    }
  });

基於這個答案

從 typescript 3.7 開始,您可以創建一個通用的遞歸類型:

type Tree<T> = T | Array<Tree<T>>

然后像這樣使用它:

let stuff: Tree<string | boolean | number> = ["lala", [1, "stuffy"], 3, false];

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM