Valoarea tipului mapat TypeScript în funcție de cheie


Pot să restrâng tipul valorii unei intrări din hartă în funcție de cheia elementului?

type Thing<T extends string = any> = {
    type: T
}

type ThingMap<T extends Thing> = {
    [K in T["type"]]: T
}

interface A {
    type: "A",
    foo: boolean,
}

interface B {
    type: "B",
}


// This compiles.
const map: ThingMap<A | B> = {
    A: { type: "A", foo: true },
    B: { type: "B" },
}

// But this also compiles, when it should not.
const map: ThingMap<A | B> = {
    A: { type: "A", foo: true },
    B: { type: "A", foo: true },
}

Răspuns #1

Vrei să te asiguri că pentru un anumit K tipul cheii nu este întreaga uniune (adică T), ci doar membrul uniunii cu tipul K. Poți folosi Extract pentru a obține membrul uniunii care are proprietatea type de tip K:

type Thing<T extends string = any> = {
    type: T
}

type ThingMap<T extends Thing> = {
    [K in T["type"]]:  Extract<T, { type : K }>  // Extract the union member that has { type: K }
}

interface A {
    type: "A",
    foo: boolean,
}

interface B {
    type: "B",
}


// This compiles.
const map: ThingMap<A | B> = {
    A: { type: "A", foo: true },
    B: { type: "B" },
}

// Err now
const map2: ThingMap<A | B> = {
    A: { type: "A", foo: true },
    B: { type: "A", foo: true },
}