Home > front end >  Type vs interface for a nested array - which to use?
Type vs interface for a nested array - which to use?

Time:06-07

I want to have a nested array of Items

type Item = { name: string }

I've come across a few approaches and I'm trying the differences in them.

  1. Using type

    type Item = { name: string }
    type NestedArray<T> = Array<T> | Array<NestedArray<T>>;
    type Items = NestedArray<Item>;
    

    But with this approach it seems I can't have Items and a nested array of Items in the same array:

    const items: Items = [
      // item, Error: Type '(Item | Item[][])[]' is not assignable to type 'Items'.
      [
        // item, Error: Type 'Item' is not assignable to type 'NestedArray<Item>'
        [
          // item, Error: Type '[Item, [any]]' is not assignable to type 'NestedArray<Item>'
          [
            item, // Works only as long as there isn't a nested array alongside item
          ]
        ]
      ]
    ]
    

    But at least it has normal Array functions:

    items.map(i => i) // works
    
  2. Using interface

    interface Items { [n: number]: Item | Items }
    
    const items: Items = [
      item
      [
        item
        [
          item
          [
            item, // All Works!
          ]
        ]
      ]
    ]
    

    But interface Items is no longer an Array (that has map etc functions)

    items.map(i => i) // Error: Property 'map' does not exist on type 'Items'.
    

How to get the best of both worlds?

  • A deeply nested array that allows items and array of items side-by-side.
  • Implements normal Array functions like map/filter etc.

CodePudding user response:

But with this approach it seems I can't have Items and a nested array of Items in the same array

That should suggest the change needed:

type NestedArray<T> = Array<T | NestedArray<T>>;

I.e. instead of "an array of T or an array of NestedArray<T>" make "an array of (T or NestedArray<T>)".

CodePudding user response:

Just extend Items interface with Array:

type Item = { name: string }


interface Items extends Array<Item | Items> { [n: number]: Item | Items }

const item = { name: 'John' }

const items: Items = [item, [item, [item, [item,],]]]

items.map(e => e) // ok

const x = items[0] //  Item | Items 

Playground

  • Related