2
votes

Comment gérer un tableau vide potentiel lors de l'accès par index dans Typescript

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 commentaires

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


3 Réponses :


2
votes

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>


0 commentaires

1
votes

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.


5 commentaires

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) - 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.



1
votes

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];
}


0 commentaires