Dans TypeScript, une propriété est considérée comme facultative si elle peut être omise d'un objet, ce qui signifie qu'elle peut être soit indéfinie, soit ne pas être fournie du tout. Les propriétés facultatives sont indiquées par le ? suffixe sur la clé de propriété. Déterminer si une propriété est facultative ou explicitement définie avec undefined comme type peut être assez délicat.
Considérons l'exemple suivant avec cinq combinaisons possibles :
type Example = { required: number; optional?: number; requiredAsUndefined: undefined; requiredWithUndefined: number | undefined; optionalWithUndefined?: number | undefined; }
Les quatre dernières propriétés peuvent être indéfinies, mais seules la deuxième et la cinquième sont en fait facultatives. Il est intéressant de noter que les propriétés facultatif, requisAvecUndéfini et facultatifAvecUndéfini résolvent toutes le même numéro de type d'union | indéfini.
Donc, ce que nous voulons, c'est un type qui renvoie vrai pour facultatif et facultatifAvecUndéfini, et faux pour le reste. Voici à quoi peut ressembler un tel type d'utilitaire :
type IsOptional<T, K extends keyof T> = undefined extends T[K] ? ({} extends Pick<T, K> ? true : false) : false; type Required = IsOptional<Example, 'required'>; // false type Optional = IsOptional<Example, 'optional'>; // true type RequiredAsUndefined = IsOptional<Example, 'requiredAsUndefined'>; // false type RequiredWithUndefined = IsOptional<Example, 'requiredWithUndefined'>; // false type OptionalWithUndefined = IsOptional<Example, 'optionalWithUndefined'>; // true
Il y a deux contraintes dans ce type d'utilitaire. La première contrainte, undéfini étend T[K], vérifie si undéfini peut faire partie du type accessible par T[K]. Il demande essentiellement si le type T[K] peut inclure un élément indéfini. La deuxième contrainte, {} étend Pick
À partir de ce type d'utilitaire, nous pouvons créer un nouveau type mappé qui ne sélectionne que les propriétés facultatives. Les propriétés non facultatives seront définies sur jamais :
type OptionalProperties<T> = { [K in keyof T]: IsOptional<T, K> extends true ? T[K] : never } type OnlyOptionals = OptionalProperties<Example>; // type OnlyOptionals = { // required: never; // optional?: number; // requiredAsUndefined: never; // requiredWithUndefined: never; // optionalWithUndefined?: number | undefined; // }
Avoir les propriétés avec type never est généralement suffisant pour la sécurité du type, mais si nous souhaitons vraiment omettre ces propriétés à des fins stylistiques, nous pouvons déplacer l'attribut IsOptional
type OnlyOptionals<T> = { [K in keyof T as IsOptional<T, K> extends true ? K : never]: T[K] } type OnlyOptionals = OnlyOptionals<Example>; // type OnlyOptionals = { // optional?: number; // optionalWithUndefined?: number | undefined; // }
Voici le Playground pour l'essayer directement dans le navigateur : TypeScript Playground
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!