Home > database >  Get type of nested conditional mapped type correcty
Get type of nested conditional mapped type correcty

Time:10-05

I have a type like this:

type BooleanResult<T> = {
  [K in keyof T]: T[K] extends object ? BooleanResult<T[K]> : boolean[]
}

Having these two types:

type ContactPerson = {
  firstName: string
  lastName: string
}
type Customer = {
  companyName: string
  contactPerson: ContactPerson
}

When creating a type from it like this:

type Result = BooleanResult<Customer>

it works as expected but the type info shows this:

type Result = {
    companyName: boolean[];
    contactPerson: BooleanResult<{
        firstName: string;
        lastName: string;
        email: string;
    }>;
}

What do I need to change to reflect correct information like this

type Result = {
    companyName: boolean[];
    contactPerson: {
        firstName: boolean[];
        lastName: boolean[];
        email: boolean[];
    };
}

CodePudding user response:

One trick that often works to force the compiler to eagerly evaluate a type is to use conditional type inference with infer to "copy" the type in question to a new type parameter, and then use the copy:

type BooleanResult<T> = {
    [K in keyof T]: T[K] extends object ? BooleanResult<T[K]> : boolean[]
} extends infer O ? O : never

For your example, this results in:

type Result = BooleanResult<Customer>
/* type Result = {
    companyName: boolean[];
    contactPerson: {
        firstName: boolean[];
        lastName: boolean[];
    };
} */

as desired.


Other "no-op" tricks that seem to have the same effect:

  • a union with the never type:

    type BooleanResult<T> = {
      [K in keyof T]: T[K] extends object ? BooleanResult<T[K]> : boolean[]
    } | never
    
  • an intersection with the unknown type:

    type BooleanResult<T> = {
      [K in keyof T]: T[K] extends object ? BooleanResult<T[K]> : boolean[]
    } & unknown
    

... (more later?)

Playground link to code

  • Related