Website-Suche

Typescript Typ 'never': wie man ihn für Objektfelder verwendet?


Ich versuche, dieses Beispiel so zum Laufen zu bringen:

interface Foo {
    a: number;
    b: string;
    c: boolean;
}

type Explode<T> = keyof T extends infer K
    ? K extends unknown
    ? { [I in keyof T]: I extends K ? T[I] : never }
    : never
    : never;


type Test = Explode<Foo>;

const test: Test = {a: 1};

was mir den folgenden Fehler gibt:

Type '{ a: number; }' is not assignable to type '{ a: number; b: never; c: never; } | { a: never; b: string; c: never; } | { a: never; b: never; c: boolean; }'.
  Type '{ a: number; }' is missing the following properties from type '{ a: number; b: never; c: never; }': b, c

Wie kann ich ein Objekt vom Typ Test erstellen, ohne den Fehler zu bekommen? Ich möchte einen Typ, der entweder das Feld a oder b oder c enthalten kann (oder ein leeres {} sein kann).

Antwort #1

Ich habe die Lösung gefunden. Ich musste die Felder von Foo optional machen, so wie folgt:

BEARBEITET, um den Vorschlag von @apokryfos zu berücksichtigen

interface Foo {
    a: number;
    b: string;
    c: boolean;
}

Jetzt kann ich:

interface Foo {
    a: number;
    b: string;
    c: boolean;
}

type AtMostOneOf<T> = keyof T extends infer K
    ? K extends unknown
    ? { [I in keyof T]+?: I extends K ? T[I] : never }
    : never
    : never;


type Test = AtMostOneOf<Foo>;

const test: Test = {a: 1}; // allowed
const test1: Test = {b: 'asd'}; // allowed
const test2: Test = {a: 1, b: 'asd'}; // not allowed
const test3: Test = {} // allowed

Spielplatz

Antwort #2

Sie können den Explode-Typ definieren als:

type Explode<T> = {
    [K in keyof T]: {
        [key in K]: T[K]
    }
}[keyof T]

dann wird type Test zu:

type Test = {
    a: number;
} | {
    b: string;
} | {
    c: boolean;
}

TS-Spielplatz

Verwandte Artikel