Wyklucz właściwość z typu


158

Chciałbym wykluczyć jedną właściwość z typu. Jak mogę to zrobić?

Na przykład mam

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

I chcę wykluczyć nieruchomości zdo zdobycia

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

Odpowiedzi:


335

W przypadku wersji TypeScript od 3.5

W języku TypeScript 3.5 Omittyp został dodany do biblioteki standardowej. Zobacz przykłady poniżej, aby dowiedzieć się, jak go używać.

W przypadku wersji TypeScript poniżej 3.5

W TypeScript 2.8 Excludetyp został dodany do standardowej biblioteki, co pozwala na zapisanie typu pominięcia po prostu jako:

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

W przypadku wersji TypeScript poniżej 2.8

Nie możesz używać Excludetypu w wersjach poniżej 2.8, ale możesz utworzyć dla niego zamiennik, aby użyć tego samego rodzaju definicji, co powyżej. Jednak to zastąpienie będzie działać tylko dla typów ciągów, więc nie jest tak potężne jak 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>>

I przykład tego typu w użyciu:

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}

Wspaniały! Deklarujesz Diff<T, U>(z typami dostępnymi dla kluczy Ti Ujako typy) jako Tpodzbiór z kluczem przecięcia 3 typów: wpisz klucz taki sam jak wartość dla T, wpisz neverfor Ui wpisz z neverdla wszystkich kluczy. Następnie przekazujesz go przez indeksator, aby uzyskać prawidłowe typy wartości. Czy mam rację?
Qwertiy,

5
Tak! Ale to ma wadę. Na przykład Omit<{a?: string, b?: boolean}, "b">wyniki w {a: string | undefined}, który nadal akceptuje undefinedjako wartość, ale traci opcjonalny modyfikator on a. :(
CRice,

To smutne ... Ciekawe, że z deklaracją i spreadem zachowuje się opcjonalny modyfikator ... Czy jest jakiś inny sposób na zachowanie tego?
Qwertiy,

1
@Qwertiy To działa! Wielkie dzięki! Edytowałem post. Zastanawiam się jednak, jaka była różnica, ponieważ to, co tam było, było dosłownie identyczne z definicją typu, o Pickile widzę.
CRice

3
Zauważ, że dla TS 3.5, definicja biblioteki standardowej Omitróżni się od podanej tutaj. W standardowym bibliotece jest to type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;Zmiana, choć niewielka, wywołała dyskusję , więc bądź świadomy różnicy.
CRice

41

W przypadku maszynopisu 2.8 można użyć nowego typu wbudowanego Exclude. Informacje o wersji 2.8 faktycznie wspominają o tym w sekcji „Wstępnie zdefiniowane typy warunkowe”:

Uwaga: Typ Exclude jest poprawną implementacją sugerowanego tutaj typu Diff. […] Nie uwzględniliśmy typu Pomiń, ponieważ jest on napisany trywialnie jako Pick<T, Exclude<keyof T, K>>.

Stosując to do twojego przykładu, typ XY można zdefiniować jako:

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

19

Znalazłem rozwiązanie polegające na zadeklarowaniu niektórych zmiennych i użyciu operatora spreadu do wnioskowania typu:

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

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

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

Działa, ale byłbym zadowolony, gdyby znalazł lepsze rozwiązanie.


3
To świetne rozwiązanie przed wersją 2.8. typeofjest jedną z bardziej niedocenianych cech maszynopisu.
Jason Hoetger,

1
Sprytne, lubię to :)! (dla wersji przed 2.8)
maxime1992

Jak mogę dodać z z ciągiem typu w twoim wyniku
user602291

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

1
Ten jest idealny dla starej wersji maszynopisu. Nie udało mi się uzyskać gotowej odpowiedzi dla wersji 2.3, ale ta działała świetnie.
k0pernikus

6

Jeśli wolisz korzystać z biblioteki, użyj 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: Znajdziesz tam wiele innych przydatnych rzeczy;)



4

W maszynie 3.5+ :

interface TypographyProps {
    variant: string
    fontSize: number
}

type TypographyPropsMinusVariant = Omit<TypographyProps, "variant">

0

Lubię to:

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);
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.