typescript - Cum pot să „dez-indexez” un tip?


Încerc să înțeleg cum să „dezindexez”.

Dat:

type Example = {
    sayHi: {
        name: string;
    } | {
        sayHi: string;
    };
    cure: {
        bool: boolean;
    } | {
        cure: string;
    };
}

Cum obțin:

({name: string; } | { sayHi: string; }) & ({bool: boolean } | { cure: string })

Am încercat, dar aplatizează totul într-o uniune.

type Example2 = Example[keyof Example]

Răspuns #1

Putem folosi o variație a UnionToIntersection care se distribuie peste cheile unui tip și intersectează valorile proprietăților:

type Example = {
    sayHi: {
        name: string;
    } | {
        sayHi: string;
    };
    cure: {
        bool: boolean;
    } | {
        cure: string;
    };
}


type UnionToIntersectionValues<U, K extends keyof U = keyof U> = 
    (K extends unknown ? (k: U[K]) => void : never) extends ((k: infer I) => void) ? I : never

type R = UnionToIntersectionValues<Example>
// type R = ({
//     name: string;
// } & {
//     bool: boolean;
// }) | ({
//     name: string;
// } & {
//     cure: string;
// }) | ({
//     sayHi: string;
// } & {
//     bool: boolean;
// }) | ({
//     sayHi: string;
// } & {
//     cure: string;
// })

Legătură către locul de joacă

Notă: Ts va muta intersecția în interior și uniunea în exterior pe baza echivalenței că (A | B) & (C | D) este (A & C) | (A & D) | (B & C) | (B & D), astfel încât tipul R este echivalent cu tipul pe care îl cauți.