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.