1

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.
1
  • I think it's probably best to declare dimensionality when you declare your variable: const items: Items[][][] = [[[{name:"blah"}]]]; One of the advantages of type annotations is to prevent excessive runtime type-checking, so it makes sense to declare things this way. Commented Jun 6, 2022 at 12:59

2 Answers 2

2

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>)".

Sign up to request clarification or add additional context in comments.

Comments

2

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.