Eduardo Dallmann
Eduardo Dallmann

Reputation: 454

How do I add the same property in all levels of a tree-like type definition in TypeScript?

I need a type generic to do self reference. And the next deep level know what the type is. Even with an error in the typescript, const v knows how to identify each property. Importantly, it is necessary to have N levels. Perhaps it would be simpler than I am thinking?

type RemoveArray<R> = R extends (infer U)[] ? U : R;

type Base<R> = RemoveArray<R> & {
  blabla: string
  data?: Base<RemoveArray<R['data']>>[]
}
type BaseArray<R> = Base<R>[]

//------

type Level2 = {
  d: string
  e: number
  //f:Level3[]
}

type Level1 = {
  a: string
  b: string
  data: Level2[]
}

const v: BaseArray<Level1> = [{
  a: 'a',
  b: 'b',
  blabla: 'lalala',
  data: [
    { blabla: 'lala', d: 'd', e: 'e' }
  ]
}]

Playground

Upvotes: 0

Views: 80

Answers (1)

GBF_Gabriel
GBF_Gabriel

Reputation: 2656

Your question could gain from clarification, so I am assuming some things from the code you've provided:

  1. All Levels have the property data: T[] if they are to include children;
  2. You have lots of types which all have the data property holding its children;
  3. The question "How do I add the same property in all levels of a tree-like type definition in TypeScript?"

So, to answer that, I suggest you use conditional types to infer when you need to declare the data property.

type ExtractDataType<T> = T extends { data: Array<infer DataType> }
  ? DataType
  : never;

type AddBlaBla<T, DataType = ExtractDataType<T>> = T & {
  blabla: string;
  data?: AddBlaBla<DataType>[];
};

This type definition allow me to make this 3-level deep type definition gain the blabla keyword:


interface Level2 {
  d: string;
  e: number;
  data: Level3[];
}

interface Level1 {
  a: string;
  b: string;
  data: Level2[];
}

interface Level3 {
  f: string;
  g: string;
}

const v: AddBlaBla<Level1>[] = [
  {
    a: "a",
    b: "b",
    blabla: "lalala",
    data: [
      {
        blabla: "s",
        d: "d",
        e: 2,
        data: [
          {
            blabla: 'blabla',
            f: "oi",
            g: "tchau",
          },
        ],
      },
    ],
  },
];

Playground

Also, may I suggest you rewrite the question title to make it easier for future reference?

Upvotes: 1

Related Questions