322 votes

Comment puis-je résoudre l'erreur 'TS2532 : Object is possibly 'undefined'' ?

J'essaie de reconstruire un exemple d'application Web qui utilise Firebase Cloud Functions et Firestore. Lors du déploiement d'une fonction, j'obtiens l'erreur suivante :

src/index.ts:45:18 - error TS2532: Object is possibly 'undefined'.
45     const data = change.after.data();

C'est la fonction :

export const archiveChat = functions.firestore
  .document("chats/{chatId}")
  .onUpdate(change => {
    const data = change.after.data();

    const maxLen = 100;
    const msgLen = data.messages.length;
    const charLen = JSON.stringify(data).length;

    const batch = db.batch();

    if (charLen >= 10000 || msgLen >= maxLen) {

      // Always delete at least 1 message
      const deleteCount = msgLen - maxLen <= 0 ? 1 : msgLen - maxLen
      data.messages.splice(0, deleteCount);

      const ref = db.collection("chats").doc(change.after.id);

      batch.set(ref, data, { merge: true });

      return batch.commit();
    } else {
      return null;
    }
  });

J'essaie juste de déployer la fonction pour la tester. J'ai déjà cherché sur le Web des problèmes similaires, mais je n'ai pas trouvé d'autres messages correspondant à mon problème.

15 votes

C'est ton vrai nom ? Sympa !

373voto

wentjun Points 9821

Avec la sortie de TypeScript 3.7, le chaînage optionnel (l'option ? ) est maintenant officiellement disponible.

Ainsi, vous pouvez simplifier votre expression comme suit :

const data = change?.after?.data();

Vous pouvez en savoir plus à ce sujet en consultant le site web de cette version. notes de mise à jour qui couvre d'autres fonctionnalités intéressantes publiées dans cette version.

Exécutez la commande suivante pour installer la dernière version stable de TypeScript.

npm install typescript

Ceci étant dit, Chaînage optionnel peut être utilisé parallèlement à Coalescence nulle pour fournir une valeur de repli lors du traitement des null o undefined valeurs

const data = change?.after?.data() ?? someOtherData();

Points supplémentaires :

Si vous utilisez le chaînage optionnel dans la conditionnelle if vous devrez toujours vous assurer que vous effectuez une vérification correcte de l'égalité des valeurs et des types.

L'opération suivante échouera en TypeScript strict, car il est possible que vous compariez une valeur indéfinie avec un nombre.

if (_?.childs?.length > 0) 

Au lieu de cela, c'est ce que vous devriez faire :

if (_?.childs && _.childs.length > 0)

45 votes

Le problème s'est posé pour un tableau sur un objet, même avec un chaînage optionnel.

2 votes

Malheureusement, il est difficile de formater le code dans les commentaires, mais voici... J'ai dû fournir la vérification de l'indéfini parce qu'il aurait lancé "Object is possibly Undefined" : if (listingData && listingData.images) { image = listingData ?.images[0] ?.imageUrl ; }

1 votes

Je me demande si images champ facultatif ici ? C'est pourquoi il pourrait être undefined ? Dans ce cas, voulez-vous essayer ceci ? if (listingData?.images) { image = listingData?.images?.[0].imageUrl; }

91voto

distante Points 801

Modifier / mettre à jour :

Si vous utilisez Typescript 3.7 ou une version plus récente, vous pouvez également le faire :

    const data = change?.after?.data();

    if(!data) {
      console.error('No data here!');
       return null
    }

    const maxLen = 100;
    const msgLen = data.messages.length;
    const charLen = JSON.stringify(data).length;

    const batch = db.batch();

    if (charLen >= 10000 || msgLen >= maxLen) {

      // Always delete at least 1 message
      const deleteCount = msgLen - maxLen <= 0 ? 1 : msgLen - maxLen
      data.messages.splice(0, deleteCount);

      const ref = db.collection("chats").doc(change.after.id);

      batch.set(ref, data, { merge: true });

      return batch.commit();
    } else {
      return null;
    }

Réponse originale

Typescript dit que change o data est éventuellement undefined (en fonction de ce que onUpdate retours).

Vous devez donc l'envelopper dans une vérification de nullité/indéfinition :

if(change && change.after && change.after.data){
    const data = change.after.data();

    const maxLen = 100;
    const msgLen = data.messages.length;
    const charLen = JSON.stringify(data).length;

    const batch = db.batch();

    if (charLen >= 10000 || msgLen >= maxLen) {

      // Always delete at least 1 message
      const deleteCount = msgLen - maxLen <= 0 ? 1 : msgLen - maxLen
      data.messages.splice(0, deleteCount);

      const ref = db.collection("chats").doc(change.after.id);

      batch.set(ref, data, { merge: true });

      return batch.commit();
    } else {
      return null;
    }
}

Si vous êtes sûr à 100% que votre object est toujours définie, alors vous pouvez mettre ceci :

const data = change.after!.data();

0 votes

Si je fais cela, j'obtiendrai l'erreur suivante : error TS7030: Not all code paths return a value. 44 .onUpdate((change, context) =>

1 votes

Vous devrez maintenant renvoyer quelque chose lorsque ce premier if renvoie un message faux.

1 votes

Oh, pour une raison quelconque, je pensais que l'erreur concernait les objets change et context. #ashamed Maintenant ça marche, mais mon code a l'air très mauvais, parce que j'ai dû ajouter une requête if pour l'objet data et ajoute simplement return null; dans les autres branches. Est-ce qu'il y a une façon plus propre de l'implémenter ? #HugeDougFan

11voto

Shiraz Points 380

Pour les autres personnes confrontées à un problème similaire au mien, où vous savez qu'une propriété particulière d'un objet ne peut pas être nulle, vous pouvez utiliser l'opérateur d'assertion non nulle ( !) après l'élément en question. Voici mon code :

  const naciStatus = dataToSend.naci?.statusNACI;
  if (typeof naciStatus != "undefined") {
    switch (naciStatus) {
      case "AP":
        dataToSend.naci.certificateStatus = "FALSE";
        break;
      case "AS":
      case "WR":
        dataToSend.naci.certificateStatus = "TRUE";
        break;
      default:
        dataToSend.naci.certificateStatus = "";
    }
  }

Et parce que dataToSend.naci ne peut pas être indéfini dans l'instruction switch, le code peut être mis à jour pour inclure des points d'exclamation comme suit :

  const naciStatus = dataToSend.naci?.statusNACI;
  if (typeof naciStatus != "undefined") {
    switch (naciStatus) {
      case "AP":
        dataToSend.naci!.certificateStatus = "FALSE";
        break;
      case "AS":
      case "WR":
        dataToSend.naci!.certificateStatus = "TRUE";
        break;
      default:
        dataToSend.naci!.certificateStatus = "";
    }
  }

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X