Exclure la propriété du type


159

Je voudrais exclure une seule propriété du type. Comment puis je faire ça?

Par exemple j'ai

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

Et je veux exclure les biens zpour obtenir

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

Réponses:


337

Pour les versions de TypeScript égales ou supérieures à 3,5

Dans TypeScript 3.5, le Omittype a été ajouté à la bibliothèque standard. Voir les exemples ci-dessous pour savoir comment l'utiliser.

Pour les versions de TypeScript inférieures à 3.5

Dans TypeScript 2.8, le Excludetype a été ajouté à la bibliothèque standard, ce qui permet à un type d'omission d'être écrit simplement comme:

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

Pour les versions de TypeScript inférieures à 2.8

Vous ne pouvez pas utiliser le Excludetype dans les versions inférieures à 2.8, mais vous pouvez créer un remplacement pour lui afin d'utiliser le même type de définition que ci-dessus. Cependant, ce remplacement ne fonctionnera que pour les types de chaîne, il n'est donc pas aussi puissant que 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>>

Et un exemple de ce type en cours d'utilisation:

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}

Génial! Vous déclarez Diff<T, U>(avec Tet Ucomme types disponibles pour les clés) comme un Tsous-ensemble à clé d'une intersection de 3 types: tapez avec clé identique à une valeur pour T, tapez avec neverfor Uet tapez avec neverpour toutes les clés. Ensuite, vous le passez via l'indexeur pour obtenir les types de valeurs corrects. Ai-je raison?
Qwertiy

5
Oui! Mais cela a un inconvénient. Par exemple, Omit<{a?: string, b?: boolean}, "b">results in {a: string | undefined}, qui accepte toujours undefinedcomme valeur, mais perd le modificateur facultatif activé a. :(
CRice

C'est triste .. Intéressant de cette façon avec declare et spread garde le modificateur optionnel ... Y a-t-il un autre moyen de le garder?
Qwertiy

1
@Qwertiy Cela fonctionne! Merci beaucoup! J'ai édité le message. Mais je me demande quelle était la différence, puisque ce qui était là était littéralement identique à la définition de type pour Pickautant que je puisse voir.
CRice

3
Notez que pour TS 3.5, la définition de la bibliothèque standard de Omitdiffère de celle donnée ici. Dans le stdlib, c'est type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;Le changement, bien que léger, a provoqué un débat , alors soyez conscient de la différence.
CRice

41

Avec typescript 2.8, vous pouvez utiliser le nouveau type intégré Exclude. Les notes de version 2.8 le mentionnent en fait dans la section «Types conditionnels prédéfinis»:

Remarque: le type Exclude est une implémentation correcte du type Diff suggéré ici. [...] Nous n'avons pas inclus le type Omit car il s'écrit trivialement comme Pick<T, Exclude<keyof T, K>>.

En appliquant ceci à votre exemple, le type XY pourrait être défini comme:

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

19

J'ai trouvé une solution en déclarant certaines variables et en utilisant l'opérateur spread pour déduire le type:

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

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

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

Cela fonctionne, mais je serais heureux de voir une meilleure solution.


3
C'est une excellente solution pré-2.8. typeofest l'une des caractéristiques les moins appréciées de la dactylographie.
Jason Hoetger

1
Intelligent, j'aime ça :)! (pour pré 2.8)
maxime1992

Comment puis-je ajouter z avec une chaîne de type dans votre résultat
user602291

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

1
Celui-ci est parfait pour l'ancienne version de dactylographié. Je n'ai pas pu obtenir la réponse acceptée pour la version 2.3, mais celle-ci a très bien fonctionné.
k0pernikus

6

Si vous préférez utiliser une bibliothèque, utilisez 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: Vous y trouverez plein d'autres trucs utiles;)



4

Dans Typescript 3.5+ :

interface TypographyProps {
    variant: string
    fontSize: number
}

type TypographyPropsMinusVariant = Omit<TypographyProps, "variant">

0

J'aime ça:

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);
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.