Maison > Article > interface Web > Pièges TypeScript : les principales erreurs commises par les développeurs et comment les éviter
TypeScript est devenu un choix populaire auprès des développeurs car il ajoute des fonctionnalités supplémentaires à JavaScript, comme la vérification du type, qui permet de détecter les erreurs avant même que le code ne s'exécute. En s'assurant que chaque variable a un type spécifique, TypeScript peut aider à éviter les erreurs courantes et à rendre le code plus facile à comprendre et à utiliser, en particulier dans les grands projets.
Cependant, lorsque les gens commencent à apprendre TypeScript, ils rencontrent souvent des problèmes courants. Ces erreurs peuvent rendre le code plus difficile à lire ou conduire à des bugs que TypeScript est censé aider à éviter. Connaître ces erreurs et savoir comment les éviter peut faire une énorme différence dans la qualité du code. Il vous aide à écrire du code plus propre et plus sûr et vous fait gagner du temps lors du débogage ultérieur. Ce guide vous guidera à travers les erreurs TypeScript les plus courantes et vous donnera des conseils pratiques pour les éviter.
Dans TypeScript, les assertions de type sont un moyen de dire à TypeScript : « Faites-moi confiance, je sais de quel type cette variable devrait être. » Par exemple, si TypeScript n'est pas sûr de quel type est quelque chose, vous pouvez utiliser une assertion de type pour le faire se comporter comme un certain type.
Voici un exemple simple :
let value: any = "Hello, world!"; let stringLength = (value as string).length;
Dans ce cas, nous disons à TypeScript : « Je sais que cette valeur est une chaîne », donc TypeScript nous permet d'utiliser des fonctionnalités de chaîne dessus (comme .length).
Bien que les assertions de type puissent être utiles, elles peuvent également causer des problèmes si elles sont mal utilisées. Lorsque vous forcez TypeScript à traiter une variable comme un certain type sans vérifications appropriées, cela peut entraîner des erreurs dans votre code, surtout si le type n'est pas réellement celui que vous pensez.
Par exemple :
let value: any = 42; let stringLength = (value as string).length; // This will throw an error at runtime
Ici, nous disons à TypeScript que la valeur est une chaîne, mais en réalité, c'est un nombre. Cela n'affichera pas d'erreur dans TypeScript, mais cela posera un problème lors de l'exécution réelle du code, entraînant des erreurs d'exécution inattendues.
Une utilisation excessive des assertions de type peut créer des problèmes car TypeScript perd une partie de sa capacité à détecter les erreurs. Les assertions de type indiquent à TypeScript « d’ignorer » le type réel d’un élément, ce qui peut aller à l’encontre de l’objectif initial de l’utilisation de TypeScript. TypeScript est destiné à aider à détecter les erreurs, mais si nous continuons à affirmer des types, il peut manquer des problèmes et laisser passer des bugs.
Utiliser l'inférence de type lorsque cela est possible : TypeScript peut souvent déterminer le type par lui-même. Au lieu d'utiliser des assertions, laissez TypeScript déduire les types là où il le peut.
Évitez d'en utiliser inutilement : Le type any peut rendre tentant l'utilisation d'assertions de type, mais any supprime la sécurité du type. Utilisez plutôt des types spécifiques, ce qui réduit le besoin d'assertions.
Ajouter des vérifications avant les assertions de type : si vous n'êtes pas sûr d'un type, vérifiez-le d'abord. Par exemple :
let value: any = "Hello, world!"; let stringLength = (value as string).length;
Les assertions de type peuvent être un outil utile, mais elles doivent être utilisées avec précaution et parcimonie. En suivant ces bonnes pratiques, vous pouvez rendre votre code TypeScript plus fiable et réduire le risque d'erreurs d'exécution.
Dans TypeScript, n'importe quel type est un moyen de dire à TypeScript : "Je ne sais pas de quel type il s'agit." Lorsque vous définissez le type d'une variable sur any, TypeScript arrête de vérifier le type de cette variable. Cela signifie que vous pouvez faire à peu près n'importe quoi avec lui (l'utiliser comme une chaîne, un nombre, un objet, etc.) sans que TypeScript ne génère d'erreurs.
Exemple :
let value: any = 42; let stringLength = (value as string).length; // This will throw an error at runtime
Bien que cela puisse sembler utile, cela peut causer des problèmes car il désactive les fonctionnalités de sécurité de TypeScript. L’intérêt de TypeScript est d’aider à détecter les erreurs en garantissant que vous utilisez les bons types. Mais lorsque vous en utilisez, TypeScript ne peut pas vérifier cette variable pour les erreurs, ce qui peut entraîner des bugs.
Par exemple :
let value: any = 42; if (typeof value === 'string') { let stringLength = (value as string).length; }
Dans ce cas, comme la valeur est quelconque, TypeScript autorise value.toUpperCase() même lorsque la valeur est un nombre, ce qui provoquera une erreur lorsque vous tenterez d'exécuter le code.
Bien que leur utilisation dans ces cas puisse sembler plus facile, cela entraîne souvent de plus gros problèmes à long terme.
let value: any = "Hello, world!"; let stringLength = (value as string).length;
let value: any = 42; let stringLength = (value as string).length; // This will throw an error at runtime
let value: any = 42; if (typeof value === 'string') { let stringLength = (value as string).length; }
En évitant tout et en utilisant des types inconnus ou spécifiques, vous pouvez rendre votre code plus sûr et réduire le risque d'erreurs inattendues, rendant votre code TypeScript plus fort et plus fiable.
Dans TypeScript, any et inconnu sont des types que vous pouvez utiliser lorsque vous n'êtes pas sûr du type exact d'une variable. Mais il y a une différence importante :
Utiliser inconnu est généralement plus sûr que n'importe quel autre car cela vous oblige à vérifier le type avant d'utiliser la variable. Cela permet d'éviter les erreurs qui peuvent survenir lorsque vous n'êtes pas sûr du type avec lequel vous travaillez.
Par exemple, imaginez que vous travaillez avec une variable et que vous ne savez pas si c'est une chaîne ou un nombre :
let value: any = "Hello!"; value = 42; // No problem, even though it started as a string.
Ici, puisque la valeur est inconnue, TypeScript ne vous permettra pas d'utiliser value.toUpperCase() tant que vous n'aurez pas confirmé qu'il s'agit d'une chaîne. Si vous essayez d'utiliser toUpperCase() sans la vérification de type, TypeScript affichera une erreur, aidant ainsi à éviter les bogues d'exécution.
Par contre, avec n'importe lequel :
let value: any = "Hello!"; console.log(value.toUpperCase()); // This is fine value = 42; console.log(value.toUpperCase()); // TypeScript won’t catch this, but it will cause an error at runtime
Si la valeur devient plus tard un nombre, ce code générera une erreur lors de son exécution et TypeScript ne vous en avertira pas. L'utilisation d'inconnu permet d'éviter ce problème en exigeant d'abord une vérification de type.
Utiliser inconnu lorsque le type est incertain : Si vous ne savez pas quel type aura une variable et que vous devez effectuer des vérifications avant de l'utiliser, utilisez inconnu. C'est plus sûr car TypeScript veillera à ce que vous vérifiiez le type avant de faire quoi que ce soit de spécifique avec.
Évitez tout lorsque cela est possible : tout devrait être un dernier recours car il supprime la vérification de type de TypeScript. N'en utilisez que si vous êtes sûr de ne pas avoir besoin de vérifier le type du tout, et cela n'a vraiment pas d'importance.
Ajouter des vérifications de type avec inconnu : Chaque fois que vous utilisez inconnu, n'oubliez pas d'ajouter des vérifications avant de l'utiliser. Cela maintient les fonctionnalités de sécurité de TypeScript actives et aide à éviter les bugs inattendus.
Préférer des types spécifiques : Si vous savez quel sera le type, utilisez ce type au lieu de tout ou inconnu. Cela rend votre code plus prévisible et plus facile à comprendre.
L'utilisation de l'inconnu peut garantir la sécurité de votre code et éviter les erreurs qui pourraient survenir avec n'importe lequel d'entre eux. Cela encourage de bonnes habitudes, comme toujours savoir avec quel type de données vous travaillez, afin de pouvoir écrire du code TypeScript plus fiable.
Dans TypeScript, null et undefined représentent des valeurs « vides » ou « non définies ».
Si vous ignorez ces valeurs « vides », cela peut entraîner des erreurs lorsque vous essayez d'utiliser des variables qui peuvent être nulles ou non définies.
Lorsque TypeScript ne prend pas en compte null ou undefined, vous pouvez essayer d'utiliser une variable comme si elle avait une valeur, pour constater qu'elle n'en a pas. Cela peut entraîner des erreurs d'exécution (des erreurs qui se produisent lors de l'exécution de votre code).
Par exemple :
let value: any = "Hello, world!"; let stringLength = (value as string).length;
Ici, user est null, donc essayer d'accéder à user.name générera une erreur. Si vous ne gérez pas les cas où les valeurs peuvent être nulles ou indéfinies, votre code pourrait s'interrompre de manière inattendue.
let value: any = "Hello, world!"; let stringLength = (value as string).length;
let value: any = 42; let stringLength = (value as string).length; // This will throw an error at runtime
Pour activer les vérifications nulles strictes, vous pouvez ajouter "strictNullChecks": true à votre fichier tsconfig.json. De cette façon, TypeScript vous demandera de gérer correctement les valeurs null et non définies, ce qui rendra votre code plus sûr.
Gérer correctement les valeurs nulles et non définies vous aide à éviter les bugs et empêche votre code de se briser lorsqu'il rencontre des valeurs vides. L'utilisation d'un chaînage facultatif, d'assertions non nulles et de vérifications nulles strictes peut rendre votre code TypeScript plus fiable et plus facile à utiliser.
Les annotations de type consistent à indiquer à TypeScript quel type une variable, une fonction ou un paramètre doit avoir. Par exemple, si vous savez qu'une variable sera toujours un nombre, vous pouvez écrire :
let value: any = 42; if (typeof value === 'string') { let stringLength = (value as string).length; }
Cela montre clairement que l’âge est un nombre. TypeScript utilise ces informations pour détecter les erreurs si vous essayez d'utiliser l'âge comme type différent, comme une chaîne.
Parfois, les gens font des erreurs avec les annotations de type, telles que :
let value: any = "Hello, world!"; let stringLength = (value as string).length;
let value: any = 42; let stringLength = (value as string).length; // This will throw an error at runtime
Lorsque vous abusez des annotations, cela peut rendre votre code répétitif et déroutant. TypeScript « déduit » (comprend) automatiquement le type de variables en fonction de leurs valeurs. Ainsi, vous n'avez pas besoin d'écrire le type à chaque fois si TypeScript peut le deviner correctement.
Par exemple, ce code :
let value: any = 42; if (typeof value === 'string') { let stringLength = (value as string).length; }
TypeScript comprend déjà que isComplete est un booléen, donc ajouter : boolean n'est pas nécessaire.
let value: any = "Hello!"; value = 42; // No problem, even though it started as a string.
let value: any = "Hello!"; console.log(value.toUpperCase()); // This is fine value = 42; console.log(value.toUpperCase()); // TypeScript won’t catch this, but it will cause an error at runtime
Laisser TypeScript gérer les types là où il le peut et ajouter des annotations claires uniquement lorsque cela est nécessaire rendra votre code plus propre, plus facile à lire et moins sujet aux erreurs. Cela permet de garder votre code TypeScript simple et facile à comprendre !
TypeScript utilise quelque chose appelé typage structurel. Cela signifie que TypeScript se soucie de la forme ou de la structure d'un objet pour décider s'il est compatible avec un certain type, plutôt que de se concentrer sur le nom du type.
En d'autres termes, si deux objets ont les mêmes propriétés et types, TypeScript les considérera comme identiques, même s'ils ont des noms différents.
Par exemple :
let value: unknown = "Hello!"; if (typeof value === "string") { console.log(value.toUpperCase()); }
Ici, coordinate et anotherCoended ont la même structure, donc TypeScript les considère comme compatibles. TypeScript ne se soucie pas si une autre Coordonnée ne s'appelle pas Point ; il vérifie uniquement s'il a des propriétés x et y avec des types numériques.
Une erreur courante est de supposer que TypeScript utilise le typage nominal (types basés sur des noms). Dans le typage nominal, deux choses doivent être exactement du même type par leur nom pour être compatibles. Mais dans le système structurel de TypeScript, si la forme correspond, TypeScript les traite comme le même type.
Par exemple, les développeurs pourraient penser que seuls les objets de type Point peuvent être affectés à des coordonnées. Cependant, TypeScript autorise tout objet ayant la même structure, quel que soit son nom de type. Cela peut prêter à confusion si vous débutez dans le typage structurel, car cela permet aux objets dont les formes correspondent à différentes parties du code d'être considérés comme du même type.
Comprendre l'approche basée sur les formes : N'oubliez pas que TypeScript se soucie davantage de la structure (propriétés et types) que des noms. Concentrez-vous sur les propriétés d'un objet plutôt que sur son nom de type.
Soyez prudent avec les propriétés supplémentaires : Si vous ajoutez des propriétés supplémentaires à un objet, il peut toujours correspondre au type attendu dans certains cas. Pour éviter toute confusion, assurez-vous que les objets n'ont que les propriétés dont ils ont besoin pour un type donné.
Utiliser des interfaces et des alias de type pour appliquer la structure : même si TypeScript est flexible avec le typage structurel, la création d'interfaces ou de alias de type peut aider à définir des structures claires et communiquer les formes prévues aux autres développeurs. Cette pratique permet de garder votre code plus compréhensible.
let value: any = "Hello, world!"; let stringLength = (value as string).length;
Le système de typage structurel de TypeScript offre de la flexibilité, mais il est important de comprendre comment il fonctionne pour éviter les surprises. En vous concentrant sur la forme des types et en utilisant des interfaces ou des alias de types, vous pouvez tirer le meilleur parti de ce système tout en gardant votre code clair et fiable.
Dans TypeScript, lorsque vous créez un objet, vous devez définir ses propriétés et les types de chaque propriété. C'est ce qu'on appelle définir la forme de l'objet. Lorsque la forme n'est pas définie correctement, cela peut entraîner des erreurs d'exécution, des erreurs qui se produisent lorsque vous exécutez votre code.
Par exemple, si vous dites qu'un objet doit avoir un nom et un âge, mais que vous oubliez d'ajouter l'âge, TypeScript peut le laisser glisser dans certains cas, mais votre code pourrait se briser plus tard lorsque vous essayez d'utiliser l'âge.
Supposons que vous définissiez un objet Utilisateur qui doit avoir un nom et un âge :
let value: any = "Hello, world!"; let stringLength = (value as string).length;
Maintenant, si vous créez un utilisateur mais oubliez d'ajouter l'âge, vous pourriez rencontrer des problèmes :
let value: any = 42; let stringLength = (value as string).length; // This will throw an error at runtime
C'est une simple erreur, mais elle peut causer des problèmes si vous vous attendez à ce que l'âge soit toujours là. Si vous ne définissez pas correctement les formes des objets, vous risquez d'ignorer accidentellement des propriétés importantes, ce qui entraînera des erreurs lorsque vous tenterez d'accéder à ces propriétés.
let value: any = 42; if (typeof value === 'string') { let stringLength = (value as string).length; }
let value: any = "Hello!"; value = 42; // No problem, even though it started as a string.
let value: any = "Hello!"; console.log(value.toUpperCase()); // This is fine value = 42; console.log(value.toUpperCase()); // TypeScript won’t catch this, but it will cause an error at runtime
En définissant soigneusement les formes des objets, vous vous assurez que chaque objet possède les champs requis, ce qui rend votre code plus fiable et réduit le risque d'erreurs. L'utilisation des outils TypeScript tels que les interfaces, les propriétés facultatives et les types d'utilitaires peut vous aider à définir des formes avec précision et à faciliter la maintenance de votre code.
Dans TypeScript, les énumérations sont un moyen de définir un ensemble de valeurs nommées. Ils vous permettent de regrouper des valeurs associées sous un seul nom. Par exemple :
let value: unknown = "Hello!"; if (typeof value === "string") { console.log(value.toUpperCase()); }
Les énumérations sont utiles lorsque vous devez représenter un ensemble limité de valeurs, telles que le statut d'une tâche. Mais parfois, abuser des énumérations peut rendre votre code plus compliqué qu'il ne devrait l'être.
let value: string = "Hello!";
Bien que cela semble correct, si vous utilisez des énumérations partout, votre code peut devenir rapidement plus difficile à comprendre, en particulier pour les développeurs qui ne sont pas familiers avec les définitions des énumérations.
Augmente la maintenance du code : Lorsque vous utilisez des énumérations partout dans votre code, mettre à jour ou modifier les valeurs ultérieurement peut être plus difficile. Vous devrez peut-être rechercher et mettre à jour l'énumération à de nombreux endroits, ce qui entraînera un travail supplémentaire.
Abstraction inutile : Parfois, les énumérations ajoutent un niveau d'abstraction qui n'est pas nécessaire. Par exemple, de simples chaînes ou nombres peuvent tout aussi bien faire l'affaire sans avoir besoin d'une énumération.
let value: any = "Hello, world!"; let stringLength = (value as string).length;
Ici, Status n'est qu'un ensemble de valeurs possibles. C'est plus simple qu'une énumération et assure toujours la sécurité des types.
let value: any = 42; let stringLength = (value as string).length; // This will throw an error at runtime
Cela garde les choses simples et claires, sans avoir besoin de créer une énumération complète.
Les énumérations sont idéales dans les cas où :
Mais pour des ensembles de valeurs simples, utiliser des types d'union ou des chaînes littérales est souvent une solution meilleure et plus simple.
En évitant la surutilisation des énumérations, votre code devient plus facile à lire, à maintenir et à comprendre, le rendant plus propre et plus efficace.
Les génériques dans TypeScript sont un moyen de créer du code réutilisable qui peut fonctionner avec n'importe quel type, tout en conservant la sécurité des types. Ils vous permettent d'écrire des fonctions, des classes ou des interfaces pouvant fonctionner avec différents types sans perdre les avantages de la vérification de type de TypeScript.
Par exemple :
let value: any = 42; if (typeof value === 'string') { let stringLength = (value as string).length; }
Dans ce cas, T est un espace réservé pour un type qui sera déterminé lorsque vous appellerez la fonction. Vous pouvez transmettre n'importe quel type (comme une chaîne, un nombre, etc.) et TypeScript veillera à ce que les types correspondent.
let value: any = "Hello, world!"; let stringLength = (value as string).length;
Ici, T est contraint d'être une chaîne, ce qui est logique pour la propriété length. Mais si vous utilisiez une contrainte inutile ou incorrecte, la fonction pourrait s'arrêter pour d'autres types.
let value: any = 42; let stringLength = (value as string).length; // This will throw an error at runtime
Cette fonction n'a pas besoin d'être générique car vous combinez simplement deux valeurs de n'importe quel type. Vous pouvez simplifier cela sans utiliser de génériques.
Utilisez les génériques uniquement lorsque cela est nécessaire : Vous n’avez pas toujours besoin de génériques. Si le code n’a pas besoin de fonctionner avec différents types, il est préférable d’utiliser simplement un type spécifique. Les génériques sont puissants mais ne doivent être utilisés que lorsqu'ils ajoutent de la valeur.
Comprendre les contraintes de type : lorsque vous utilisez des génériques, assurez-vous que les contraintes ont du sens. Limitez uniquement les types qui doivent être restreints. Par exemple, si vous travaillez avec des tableaux, utilisez T[] ou Array
let value: any = 42; if (typeof value === 'string') { let stringLength = (value as string).length; }
Simplifiez là où c'est possible : Ne compliquez pas trop le code avec des génériques inutiles. Si un type simple (comme une chaîne ou un nombre) fonctionne bien, n'essayez pas de le généraliser avec des génériques. Utilisez des génériques lorsque vous souhaitez rendre une fonction ou une classe flexible avec différents types.
Utiliser les génériques par défaut : Si vous souhaitez faciliter l'utilisation des génériques, vous pouvez attribuer un type par défaut au cas où l'utilisateur n'en fournirait pas.
let value: any = "Hello!"; value = 42; // No problem, even though it started as a string.
Ici, si l'utilisateur ne spécifie pas de type, T sera par défaut une chaîne.
En comprenant comment fonctionnent les génériques et quand les utiliser, vous pouvez éviter les erreurs courantes et rendre votre code plus flexible, lisible et maintenable.
TypeScript possède un fichier de configuration appelé tsconfig.json dans lequel vous pouvez définir diverses options pour personnaliser la façon dont TypeScript compile votre code. Cette configuration vous permet d'appliquer des règles plus strictes et de détecter les erreurs potentielles plus tôt, avant qu'elles ne causent des problèmes dans votre code.
Si vous ne faites pas attention à la configuration de TypeScript, il se peut qu'il ne détecte pas certaines erreurs ou problèmes susceptibles d'entraîner des bugs ou des problèmes dans votre code. Par exemple, TypeScript peut vous permettre d'écrire du code qui serait normalement signalé comme incorrect si les bons paramètres étaient activés.
En ignorant ces paramètres, vous risquez de manquer des avertissements importants et de rendre votre code moins sûr.
Pourquoi c'est important : lorsque strict est activé, TypeScript vérifie des éléments tels que les variables non initialisées, les vérifications nulles, etc. Cela vous aide à détecter rapidement les problèmes potentiels.
let value: any = "Hello, world!"; let stringLength = (value as string).length;
Pourquoi c'est important : Avec noImplicitAny, TypeScript vous oblige à spécifier un type, vous empêchant d'utiliser accidentellement des bogues potentiels et de manquer des bogues potentiels que la vérification de type détecterait autrement.
let value: any = 42; let stringLength = (value as string).length; // This will throw an error at runtime
Pourquoi c'est important : Sans ce paramètre, TypeScript permettra d'attribuer null et undefined à n'importe quelle variable, ce qui peut entraîner des erreurs d'exécution.
let value: any = 42; if (typeof value === 'string') { let stringLength = (value as string).length; }
Activer le mode strict : activez toujours l'indicateur strict dans votre tsconfig.json. Cela activera automatiquement plusieurs paramètres utiles, notamment noImplicitAny et strictNullChecks. C'est l'un des meilleurs moyens de garantir que votre code est aussi sûr et exempt d'erreurs que possible.
Réviser et personnaliser les paramètres : prenez un moment pour consulter la liste complète des options du compilateur TypeScript. Personnalisez-les pour répondre aux besoins de votre projet. Vous pouvez activer ou désactiver certaines vérifications pour rendre votre code plus fiable et maintenable.
Toujours activer noImplicitAny : évitez tout type, sauf en cas d'absolue nécessité. En activant noImplicitAny, vous serez obligé de réfléchir aux types de vos variables, ce qui rendra votre code plus sûr.
Utilisez strictNullChecks pour détecter les erreurs nulles : Les valeurs nulles peuvent facilement provoquer des bugs si elles ne sont pas traitées avec soin. En activant strictNullChecks, vous vous assurez que les valeurs nulles ou non définies ne se glissent pas dans des endroits où elles peuvent causer des problèmes.
En configurant correctement les paramètres de TypeScript, vous pouvez éviter les pièges courants et rendre votre code plus fiable, plus facile à maintenir et moins sujet aux bugs.
TypeScript est un outil puissant qui peut aider les développeurs à écrire du code plus sûr et plus fiable, mais il est facile de commettre des erreurs lorsque vous débutez. Nous avons couvert les pièges TypeScript les plus courants, tels que l'utilisation abusive des assertions de type, leur utilisation excessive, l'ignorance de la nullité et la mauvaise compréhension des génériques. Ces erreurs peuvent entraîner des bugs inattendus et un code plus difficile à maintenir.
Voici une liste de contrôle rapide pour éviter ces erreurs :
En comprenant ces erreurs courantes et en suivant les meilleures pratiques décrites dans cet article, vous serez en mesure d'écrire du code TypeScript plus propre, plus sûr et plus maintenable.
Adoptez les fonctionnalités de TypeScript et laissez-le vous aider à écrire des applications plus fiables avec moins de bugs. Continuez à apprendre et bon codage !
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!