TypeScript et sa question éternelle : comment rendre un type nullable ?
\n\nBonjour, collègue ! Si tu as déjà écrit en TypeScript, tu as sûrement rencontré une situation où une fonction peut retourner une valeur, ou pas. Ou une variable qui n'est pas initialisée immédiatement. Et là se pose la question cruciale : comment déclarer un type qui peut être null ou undefined ?
Cette question est l'une des plus populaires sur Stack Overflow (des dizaines de milliers de vues !), et ce n'est pas pour rien. TypeScript est strict, mais juste. Il ne nous permet pas de simplement assigner null à une variable de type string. Et c'est excellent, car cela évite une multitude de bugs. Mais que faire quand nullable fait partie de la logique métier ? Voyons cela.
Dans cet article, nous ne donnerons pas seulement une réponse sèche. Nous irons des bases aux techniques avancées, analyserons les erreurs fréquentes et apprendrons à écrire un code à la fois sûr et élégant. C'est parti !
\n\nLes bases : Union Types et Null
\n\nLa manière la plus simple et directe de rendre un type nullable est d'utiliser un union type (type union). Si une variable peut être une chaîne ou null, on écrit :
\n\nlet userName: string | null = null;\nuserName = "Alice"; // Ok\nuserName = null; // Ok aussi\n\n\nLa même chose fonctionne avec undefined. En TypeScript, null et undefined sont des types différents (sauf si le flag --strictNullChecks est désactivé, mais nous y reviendrons).
let age: number | undefined;\nage = 25;\nage = undefined; // Fonctionne\n\n\nImportant : si tu utilises | null ou | undefined, TypeScript t'obligera à vérifier la valeur avant de l'utiliser. Tenter d'appeler une méthode sur un objet potentiellement null entraînera une erreur de compilation. C'est cette "sécurité" que nous aimons dans TS.
Exemple concret : recherche d'un utilisateur
\n\ninterface User {\n id: number;\n name: string;\n}\n\nfunction findUser(id: number): User | null {\n // ...logique de recherche\n if (id === 1) {\n return { id: 1, name: "Ivan" };\n }\n return null;\n}\n\nconst user = findUser(2);\n// user.name; // Erreur ! 'user' peut être null\nif (user) {\n console.log(user.name); // Maintenant c'est sûr\n}\n\n\nTu vois ? Le compilateur te dit lui-même : "Hé, vérifie d'abord, sinon tu vas planter !". Cela permet d'économiser des heures de débogage.
\n\nParamètres et propriétés optionnels (Optional Chaining)
\n\nSouvent, ce ne sont pas seulement les variables qui sont nullables, mais aussi les champs d'objets ou les arguments de fonctions. Pour cela, TypeScript propose une syntaxe spéciale : le modificateur optionnel (le point d'interrogation ?).
Paramètres optionnels de fonction
\n\nfunction greet(name?: string) {\n if (name) {\n return `Bonjour, ${name} !`;\n }\n return "Bonjour, inconnu !";\n}\n\nconsole.log(greet("Pierre")); // Bonjour, Pierre !\nconsole.log(greet()); // Bonjour, inconnu !\n\n\nLe type du paramètre name devient automatiquement string | undefined. Note : si un paramètre est optionnel, tu peux ne pas le passer, et TS ne râlera pas.
Propriétés optionnelles d'interfaces
\n\ninterface Config {\n url: string;\n port?: number; // peut être number ou undefined\n}\n\nconst config1: Config = { url: "http://localhost" }; // port absent\nconst config2: Config = { url: "http://localhost", port: 3000 };\n\n\nEn accédant à config1.port, TypeScript te dira que c'est number | undefined. Et c'est correct — on ne sait pas si le port est défini.
Chaînage optionnel (Optional Chaining) — votre meilleur ami
\n\nAvec l'arrivée d'ES2020 et de TypeScript 3.7, nous avons une manière élégante d'accéder en toute sécurité à des propriétés imbriquées qui peuvent être null ou undefined. Cela s'appelle le optional chaining