ProgrammationDéveloppeur Frontend

Comment fonctionne l'opérateur 'in' pour vérifier la présence d'une propriété dans un objet en TypeScript, et quelle est la différence entre son utilisation et une simple vérification sur undefined ? Quand et pourquoi utiliser cet opérateur en programmant en TypeScript ?

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse.

Historique de la question:

L'opérateur in a été hérité de JavaScript par TypeScript et est largement utilisé pour vérifier la présence d'une propriété dans un objet. En TypeScript, sa sémantique prend une signification supplémentaire en raison du système de types — il est important non seulement d'avoir une valeur, mais aussi de l'avoir déclarée au niveau du type, notamment dans les cas de propriétés optionnelles.

Problème:

Les développeurs de TypeScript confondent souvent la simple vérification sur undefined avec la vérification de la présence de la propriété elle-même dans l'objet. Une erreur peut survenir si la propriété existe, mais sa valeur est undefined ou si elle est héritée plutôt que définie directement sur l'objet.

Solution:

L'opérateur in vérifie si la propriété est réellement présente dans la chaîne de prototypes de l'objet, indépendamment de sa valeur. Cela joue un rôle important lors de la vérification de propriétés optionnelles ou calculées, ce qui permet d'éviter le traitement inattendu de valeurs falsy :

Exemple de code :

interface User { id: number; name?: string; } const user1: User = { id: 1 }; const user2: User = { id: 2, name: undefined }; console.log('name' in user1); // false console.log('name' in user2); // true

Caractéristiques clés :

  • L'opérateur in détermine la présence d'une propriété dans un objet ou son prototype, et non seulement l'existence d'une valeur.
  • Ne dépend pas de la valeur de la propriété (peut être undefined, null, et même false).
  • Particulièrement utile lors de la manipulation de propriétés optionnelles et de types avec des discriminants.

Questions pièges.

Quelle est la différence entre la vérification de undefined (obj.prop !== undefined) et l'utilisation de in ?

La vérification sur undefined détermine seulement la valeur, mais non la présence de la propriété. Si la propriété existe mais est undefined, le résultat sera true. Si la propriété n'existe pas du tout, sa valeur sera également undefined, mais sémantiquement, ce sont des cas différents.

Exemple :

const obj: any = { foo: undefined }; console.log('foo' in obj); // true console.log(obj.foo !== undefined); // false console.log('bar' in obj); // false console.log(obj.bar !== undefined); // false

L'opérateur in peut-il vérifier la présence d'une propriété uniquement sur l'objet lui-même, en ignorant la chaîne de prototypes ?

Non, l'opérateur in standard vérifie également les prototypes. Pour vérifier uniquement les propriétés propres, utilisez la méthode hasOwnProperty :

const obj = Object.create({ foo: 123 }); obj.bar = 456; console.log('foo' in obj); // true console.log(obj.hasOwnProperty('foo')); // false

Peut-on utiliser l'opérateur in pour le narrowing de types union en TypeScript ?

Oui, en TypeScript, in ressemble à un union discriminé et permet de réduire le type à une variante spécifique :

type Shape = { kind: 'circle'; radius: number } | { kind: 'square'; size: number }; function getArea(shape: Shape) { if ('radius' in shape) { // Ici shape est un cercle return Math.PI * shape.radius ** 2; } // Ici shape est un carré return shape.size ** 2; }

Erreurs courantes et anti-patterns

  • Confondre la simple vérification sur undefined avec la vérification in.
  • Utiliser in pour les tableaux (sur les tableaux, retourne true pour les indices numériques et les propriétés héritées).
  • Essayer d'utiliser in pour des valeurs autres que des objets (par exemple, null ou undefined).

Exemple de la vie réelle

Cas négatif

Dans un projet avec un tableau d'utilisateurs, on vérifiait un champ optionnel avec user.name !== undefined, ce qui entraînait une logique incorrecte pour les utilisateurs dont la propriété était explicitement définie comme undefined.

Avantages :

  • Mise en œuvre rapide et simple.

Inconvénients :

  • Erreurs en cas de présence d'un champ avec undefined.
  • Problèmes lors du refactoring si le schéma des données change.

Cas positif

On utilisait in pour vérifier précisément la présence d'un champ optionnel chez l'utilisateur, indépendamment de sa valeur, ce qui a permis de différencier correctement "champ absent" et "champ présent mais valeur non spécifiée".

Avantages :

  • Logique commerciale correcte.
  • Le code est plus facile à maintenir, avec moins d'erreurs cachées.

Inconvénients :

  • Nécessite de connaître la sémantique de l'opérateur in, ce qui n'est pas toujours évident pour les débutants.