Home > database >  How to keep union type inside other type instead of destructure it
How to keep union type inside other type instead of destructure it

Time:06-11

I have this type

type Test = {
  checked: boolean;
  selection: 'female' | 'male'
}

And, I would like to transform it into another type such as

type Test = {
  checked: Record<string, boolean>;
  selection: Record<string, 'female' | 'male'>
}

Then, I wrote this transform

type NestedTest<T> = T extends object
  ? { [P in keyof T]: NestedTest<T[P]> }
  : Record<string, T>;

But, when I call it like

type Test2 = NestedTest<Test>;

Then I got the unexpected results below

type Test2 = {
    checked: Record<string, false> | Record<string, true>;
    selection: Record<string, "female"> | Record<string, "male">;
}

As you can see, typescript auto splits these union types into a union of Record type instead of only one.

I don't why it is like that. If you can, please tell me what I misunderstood? and how to fix it.

Here is my playground

Thank you so much!

CodePudding user response:

You basically need to stop the unions from distributing to seperate Records. See Distributive Conditional Types in the TypeScript docs.

type NestedTest<T> = [T] extends [object]
  ? { [P in keyof T]: NestedTest<T[P]> }
  : Record<string, T>;

If we surround T and object with square brackets, the elements of the union will not be distributed to different Records.

Playground

  • Related