Quelle est la manière préférée d'accéder aux éléments par index dans un tableau dans Typescript lorsque le tableau peut également être vide, ce qui conduit à des éléments indéfinis
?
Je suis en train de coder un jeu simple dans React avec Typescript où j'ai une variable game
constituée d'un tableau d'ensembles de type ISet
. Dans cet exemple simplifié, ISet
a une propriété score
dans son interface, à laquelle j'essaie d'accéder
const game: Array<ISet | undefined> = [];
Comment puis-je Typecript détecte que currentSet
est potentiellement indéfini
ici?
J'ai essayé de définir manuellement le type de currentSet
sur
const currentSet: ISet | undefined = game[game.length - 1];
mais cela ne fonctionne pas, et changer la déclaration de type en
const game: ISet[] = []; const currentSet = game[game.length - 1]; // 'currentSet' will be of type 'ISet', although it will be 'undefined' here console.log(currentSet.score); // No Typescript error, although a 'Uncaught TypeError: Cannot read property 'score' of undefined' error will be thrown when run
permet undefined code> à ajouter au tableau, ce qui n'est pas ce que je recherche et qui entraînera des problèmes plus tard.
J'ai lu quelques problèmes sur GitHub, aime celui-ci , mais je n'ai trouvé aucune suggestion sur des solutions de contournement. Utiliser quelque chose comme last from Underscore fonctionnerait, mais il semble un peu exagéré pour un nouveau package de contourner ce problème .
Dans l'attente de l'aide!
Andreas
3 Réponses :
La meilleure solution que j'ai pu trouver était d'utiliser last from lodash et de l'ajouter comme un package distinct . J'ai également ajouté des définitions de type séparément en installant @ types / lodash.last
.
Mon exemple de cas ci-dessus ressemblerait à ceci:
import last from 'lodash.last' const game: ISet[] = []; const currentSet = last(game); // 'currentSet' now has a type of 'ISet | undefined' ð¤ console.log(currentSet.score); // Object is possibly 'undefined'. ts(2532) ð
p>
Cela me semble normal, vous avez un tableau de ISet
, mais il est juste vide pour le moment. les tableaux peuvent être vides, c'est ainsi que fonctionnent les tableaux.
il suffit de vérifier si le tableau contient des éléments en premier
[{score: 4}, {score: 1}, undefined, {score: 5}, undefined, undefined, {score: 10}]
Faire quelque chose comme game: (ISet | undefined) []
peut impliquer que même lorsqu'il est rempli, tout élément du tableau peut être indéfini
comme ceci:
const game: ISet[] = []; if (game.length) { const currentSet = game[game.length - 1]; console.log(currentSet.score); } else { console.log("no games!"); }
ce qui n'est probablement pas votre intention (je suppose). Cela pourrait vous embrouiller, vous ou d'autres développeurs à l'avenir.
Le problème ici est qu'il n'y a pas d'erreur à la compilation .
Encore une fois, je pense que c'est assez normal. Je suppose que cet exemple est un pseudo-code et que vous n'initialisez probablement pas réellement un tableau vide, puis n'essayez pas d'accéder à l'index -1
dessus (longueur 0 puis soustrayez 1) i > - Votre tableau en code réel obtient probablement des valeurs de quelque chose ... c'est donc généralement une bonne idée de vous assurer qu'un tableau contient des valeurs avant d'essayer d'y accéder.
De plus, gardez à l'esprit que le compilateur ne garde pas vraiment trace du nombre d'éléments dans le tableau, c'est quelque chose qui se produit au moment de l'exécution. Si j'ai exécuté someArr [9999]
, je ne m'attends pas à ce que le compilateur TS sache que mon tableau ne contient que 421 éléments, c'est à moi de vérifier.
Que ce soit normal n'est pas le point. Vous voulez attraper autant de problèmes le plus tôt possible, et demander au compilateur de renvoyer le type manifestement correct serait génial.
oui, vous l'avez défini comme un tableau d'objets ISet
, c'est donc ce qu'il renvoie. Si vous accédez à un élément du tableau qui n'existe pas, ce n'est pas un problème de compilation.
Eh bien, vous pouvez implémenter votre propre dernier
et être plus précis dans sa saisie:
function last<T>(array: T[]): T | undefined // Explicit type { return array[array.length - 1]; }
Bizarre ... sauf si vous avez une version horriblement ancienne de tslint, cela devrait fonctionner. Essayez d'exécuter
tslint -v
peut-être qu'une version globale de tslint est installée et qu'elle est en train d'être récupérée.À quelle règle tslint vous référez-vous qui attraperait cela? no-spare-arrays ne fonctionnera pas ici. J'utilise la version 5.13, donc cela ne devrait pas être le problème.
Voilà: github.com/danielnixon/eslint-plugin-total-functions