【问题标题】:Recursive array type typescript递归数组类型打字稿
【发布时间】:2021-12-17 08:56:08
【问题描述】:

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

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

这可以在 Typescript 中实现吗?

【问题讨论】:

    标签: typescript


    【解决方案1】:

    类型别名不能引用自己,所以这种幼稚的方法会失败:

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

    【讨论】:

      【解决方案2】:

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

      type RArray = (string | RArray)[];
      

      如果你想在递归函数中定义一个泛型,可以使用interface ...&lt;T&gt; extends (T|...&lt;T&gt;)[]

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

      【讨论】:

        【解决方案3】:

        基于this answer

        从 typescript 3.7 开始,您可以创建通用递归类型:

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

        然后像这样使用它:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-07-10
          • 2019-04-09
          • 2021-12-15
          • 2021-06-30
          相关资源
          最近更新 更多