Eigenschaft vom Typ ausschließen


155

Ich möchte eine einzelne Eigenschaft vom Typ ausschließen. Wie kann ich das machen?

Zum Beispiel habe ich

interface XYZ {
  x: number;
  y: number;
  z: number;
}

Und ich möchte Eigentum ausschließen z, um zu bekommen

type XY = { x: number, y: number };

Antworten:


330

Für Versionen von TypeScript ab 3,5

In TypeScript 3.5 wurde der OmitTyp zur Standardbibliothek hinzugefügt. In den folgenden Beispielen finden Sie Informationen zur Verwendung.

Für Versionen von TypeScript unter 3.5

In TypeScript 2.8 wurde der ExcludeTyp zur Standardbibliothek hinzugefügt, sodass ein Auslassungstyp einfach wie folgt geschrieben werden kann:

type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>

Für Versionen von TypeScript unter 2.8

Sie können den ExcludeTyp nicht in Versionen unter 2.8 verwenden, aber Sie können einen Ersatz dafür erstellen, um dieselbe Definition wie oben zu verwenden. Diese Ersetzung funktioniert jedoch nur für Zeichenfolgentypen und ist daher nicht so leistungsfähig wie Exclude.

// Functionally the same as Exclude, but for strings only.
type Diff<T extends string, U extends string> = ({[P in T]: P } & {[P in U]: never } & { [x: string]: never })[T]
type Omit<T, K extends keyof T> = Pick<T, Diff<keyof T, K>>

Und ein Beispiel für diesen Typ:

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

// Omit a single property:
type OmitA = Omit<Test, "a">; // Equivalent to: {b: number, c: boolean}

// Or, to omit multiple properties:
type OmitAB = Omit<Test, "a"|"b">; // Equivalent to: {c: boolean}

Toll! Sie deklarieren Diff<T, U>(mit Tund Uals für Schlüssel verfügbare Typen) als TTeilmenge einer Schnittmenge von 3 Typen mit Schlüssel: Typ mit Schlüssel, der dem Wert für entspricht T, Typ mit neverfür Uund Typ mit neverfür alle Schlüssel. Dann übergeben Sie es durch den Indexer, um die richtigen Wertetypen zu erhalten. Habe ich recht?
Qwertiy

5
Ja! Dies hat jedoch einen Nachteil. Beispielsweise Omit<{a?: string, b?: boolean}, "b">ergibt sich {a: string | undefined}, was immer noch undefinedals Wert akzeptiert , aber den optionalen Modifikator ein verliert a. :(
CRice

Das ist traurig. Interessant auf diese Weise mit Deklarieren und Verbreiten bleibt optionaler Modifikator ... Gibt es eine andere Möglichkeit, es zu behalten?
Qwertiy

1
@ Qwertiy Es funktioniert! Danke vielmals! Ich habe den Beitrag bearbeitet. Aber ich frage mich, was der Unterschied war, da das, was da war, Picksoweit ich sehen kann, buchstäblich mit der Typdefinition identisch war .
CRice

3
Beachten Sie, dass sich die Definition der Standardbibliothek für TS 3.5 Omitvon der hier angegebenen unterscheidet. In der stdlib ist es type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;Die Änderung, obwohl geringfügig, hat einige Debatten ausgelöst , seien Sie sich also des Unterschieds bewusst.
CRice

41

Mit Typoskript 2.8 können Sie den neuen integrierten ExcludeTyp verwenden. In den Versionshinweisen zu 2.8 wird dies im Abschnitt "Vordefinierte bedingte Typen" erwähnt:

Hinweis: Der Exclude-Typ ist eine ordnungsgemäße Implementierung des hier vorgeschlagenen Diff-Typs. [...] Wir haben den Omit-Typ nicht aufgenommen, da er trivial als geschrieben ist Pick<T, Exclude<keyof T, K>>.

Wenn Sie dies auf Ihr Beispiel anwenden, kann der Typ XY wie folgt definiert werden:

type XY = Pick<XYZ, Exclude<keyof XYZ, "z">>

19

Ich habe eine Lösung gefunden , indem ich einige Variablen deklariert und den Spread-Operator verwendet habe, um auf den Typ zu schließen:

interface XYZ {
  x: number;
  y: number;
  z: number;
}

declare var { z, ...xy }: XYZ;

type XY = typeof xy; // { x: number; y: number; }

Es funktioniert, aber ich würde mich über eine bessere Lösung freuen.


3
Dies ist eine großartige Lösung vor 2.8. typeofist eines der am meisten unterschätzten Merkmale von Typoskript.
Jason Hoetger

1
Clever, ich mag es :)! (für vor 2.8)
maxime1992

Wie ich z mit Typ Zeichenfolge in Ihrem Ergebnis hinzufügen kann
user602291

@ user602291 , type Smth = XY & { z: string };?
Qwertiy

1
Dieser ist perfekt für alte Versionen von Typoskript. Ich konnte die Antwort nicht bekommen, um für 2.3 zu arbeiten, aber diese funktionierte großartig.
k0pernikus

6

Wenn Sie eine Bibliothek bevorzugen, verwenden Sie ts-essentials .

import { Omit } from "ts-essentials";

type ComplexObject = {
  simple: number;
  nested: {
    a: string;
    array: [{ bar: number }];
  };
};

type SimplifiedComplexObject = Omit<ComplexObject, "nested">;

// Result:
// {
//  simple: number
// }

// if you want to Omit multiple properties just use union type:
type SimplifiedComplexObject = Omit<ComplexObject, "nested" | "simple">;

// Result:
// { } (empty type)

PS: Dort findest du viele andere nützliche Dinge;)



4

In Typescript 3.5+ :

interface TypographyProps {
    variant: string
    fontSize: number
}

type TypographyPropsMinusVariant = Omit<TypographyProps, "variant">

0

Das gefällt mir:

interface XYZ {
  x: number;
  y: number;
  z: number;
}
const a:XYZ = {x:1, y:2, z:3};
const { x, y, ...last } = a;
const { z, ...firstTwo} = a;
console.log(firstTwo, last);
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.