Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Recursive type name [duplicate]

Tags:

typescript

I want to create an object which can have either primitives or objects like itself as properties. I mean something like that would be wrong:

const obj: DesiredType = {
  correctProp1: 'string',
  correctProp2: 123,
  correctProp3: true,
  wrongProp4: [1, 2, 3],
  prop5: {
    wrongProp1: () => {},         // Is neither an object nor a primitive
    wrongProp2: [1, 2, 3],        // Same
    correctProp3: 'other string'
  }
}

I don't want to just use Record<string, any>, because this way anything can be put there (function, array, etc). Using something like following:

Record<string, string | number | boolean | Record<string, any>>

would also be bad, because anything can appear on the second level

I have tried this:

type PrimitiveOrObject = string | number | boolean | Record<string, PrimitiveOrObject>; // ts(2456) type 

DesiredType = Record<string, PrimitiveOrObject>;

But I get error ts(2456): Type alias "PrimitiveOrObject" circularly references itself.

So is there a way to create a type alias for objects which contain either primitives or objects like itself?

like image 408
Макс Кудрин Avatar asked Oct 11 '25 11:10

Макс Кудрин


1 Answers

You can't use a type alias generically in the same definition that creates it. But you can use it in object type literals, so if we add a little bit of indirection, we can get the recursion you want.

type PrimitiveOrObject =
  string | number | boolean | { [key: string]: PrimitiveOrObject };

The { [key: string]: PrimitiveOrObject } syntax is called an index signature. For the key type of string, it's equivalent to Record (see this question for details), but it has the benefit of being inside an object literal and thus not subject to the recursion restriction you've run afoul of.

like image 117
Silvio Mayolo Avatar answered Oct 16 '25 13:10

Silvio Mayolo



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!