web-dev-qa-db-fra.com

Comment supprimer TypeScript "erreur TS2533: l'objet est peut-être 'null' ou 'indéfini'"?

J'ai un type:

type tSelectProtected = {
  handleSelector?: string,
  data?: tSelectDataItem[],

  wrapperEle?: HTMLElement,
  inputEle?: HTMLElement,
  listEle?: HTMLElement,
  resultEle?: HTMLElement,

  maxVisibleListItems?: number
}

Je déclare une variable globale - module sage:

var $protected : tSelectProtected = {};

J'attribue la valeur appropriée dans la portée de function1:

$protected.listEle = document.createElement('DIV');

J'appelle, plus tard, dans la portée de function2:

$protected.listEle.classList.add('visible');

Je reçois une erreur TypeScript:

error TS2533: Object is possibly 'null' or 'undefined'

Je sais que je peux effectuer une vérification explicite à l'aide de if ($protected.listEle) {$protected.listEle} pour calmer le compilateur, mais cela semble très peu pratique pour la plupart des cas non triviaux.

Comment cette situation peut ou doit être gérée sans désactiver les contrôles du compilateur TS?

78
grasnal

Cette fonctionnalité est appelée "vérification de null strict". Pour la désactiver, assurez-vous que le drapeau du compilateur --strictNullChecks n'est pas défini.

Cependant, l'existence de null a été décrite comme L'erreur d'un milliard de dollars , il est donc excitant de voir des langages tels que TypeScript introduire un correctif. Je recommande fortement de le garder allumé.

Une solution consiste à s'assurer que les valeurs ne sont jamais null ou undefined, par exemple en les initialisant à l'avance:

interface SelectProtected {
    readonly wrapperElement: HTMLDivElement;
    readonly inputElement: HTMLInputElement;
}

const selectProtected: SelectProtected = {
    wrapperElement: document.createElement("div"),
    inputElement: document.createElement("input")
};
34
Douglas

Si vous savez de manière externe qu'une expression n'est pas null ou undefined, vous pouvez utiliser l'opérateur d'assertion non null ! pour contraindre ces types

// Error, some.expr may be null or undefined
let x = some.expr.thing;
// OK
let y = some.expr!.thing;
302
Ryan Cavanaugh

J'ai utilisé:

if (object !== undefined) {
    // continue - error suppressed when used in this way.
}

Alternativement, vous pouvez utiliser le type coercition:

const objectX = object as string

Avant de choisir l'une des solutions de contournement ci-dessus, tenez compte de l'architecture que vous visez et de son impact sur l'ensemble.

14
JoshuaTree

Si vous savez que le type ne sera jamais null ou undefined, vous devez le déclarer comme foo: Bar sans le ?. Déclarer un type avec la syntaxe ? Bar signifie qu'il peut potentiellement être indéfini, ce que vous devez vérifier.

En d'autres termes, le compilateur fait exactement ce que vous lui demandez. Si vous voulez que ce soit facultatif, vous aurez besoin de la vérification plus tard.

9
ssube

Ce n'est pas le problème de l'OP, mais j'ai reçu le même message Object is possibly 'null' quand j'avais déclaré un paramètre avec le type null par accident:

something: null;

au lieu de lui attribuer la valeur null:

something: string = null;
5
thinkOfaNumber

Cette solution a fonctionné pour moi:

  • accédez à tsconfig.json et ajoutez "strictNullChecks": false

 enter image description here

5
Mahesh Nepal

En option, vous pouvez utiliser un transtypage. Si vous avez cette erreur de TypeScript, cela signifie qu'une variable a un type ou n'est pas définie:

let a: string[] | undefined;

let b: number = a.length; // [ts] Object is possibly 'undefined'
let c: number = (a as string[]).length; // ok

Assurez-vous que a existe vraiment dans votre code.

4
Shevchenko Viktor

J'y suis allé avec React lors du réglage de l'état et de l'utilisation de map.

Dans ce cas, je passais un appel d'extraction d'API et la valeur de la réponse n'était pas connue, mais devrait avait la valeur "Réponse". J'ai utilisé un type personnalisé pour cela, mais comme la valeur pouvait être null, j'ai quand même eu une erreur TS. Autoriser le type à être null ne le répare pas; sinon, vous pouvez utiliser un default parameter value, mais c'était compliqué pour mon cas.

Je l'ai surmonté en fournissant une valeur par défaut dans le cas où la réponse était vide en utilisant simplement un opérateur ternaire:

this.setState({ record: (response.Answer) ? response.Answer : [{ default: 'default' }] });
1
Chris Shaffer

Dans ReactJS, je vérifie dans le constructeur si les variables sont nulles, si elles le sont, je le traite comme une exception et je gère l’exception de manière appropriée. Si les variables ne sont pas nulles, le code continue et le compilateur ne se plaint plus après ce point:

private variable1: any;
private variable2: any;

constructor(props: IProps) {
    super(props);

    // i.e. here I am trying to access an HTML element
    // which might be null if there is a typo in the name
    this.variable1 = document.querySelector('element1');
    this.variable2 = document.querySelector('element2');

    // check if objects are null
    if(!this.variable1 || !this.variable2) {
        // Manage the 'exception', show the user a message, etc.
    } else {
        // Interpreter should not complain from this point on
        // in any part of the file
        this.variable1.disabled = true; // i.e. this line should not show the error
    }
0
Gedeon

Dans TypeScript, vous pouvez procéder comme suit pour supprimer la error

let subString?: string;

subString > !null; - Notez le point d'exclamation ajouté avant null.

0
user3834142

Astuce pour RxJS

J'aurai souvent des variables de membre de type Observable<string>, et je ne l'initialiserai pas avant ngOnInit (en utilisant Angular). Le compilateur suppose alors qu'il ne s'agit pas d'une initialisation, car il n'est pas "définitivement attribué dans le constructeur" - et le compilateur ne comprendra jamais ngOnInit.

Vous pouvez utiliser l'opérateur d'assertion ! sur la définition pour éviter l'erreur:

favoriteColor!: Observable<string>;

Une observable non initialisée peut causer toutes sortes de problèmes d'exécution avec des erreurs telles que "vous devez fournir un flux mais vous avez fourni la valeur null". Le ! convient si vous décidément savez que cela va être défini dans quelque chose comme ngOnInit, mais il peut arriver que la valeur soit définie d'une autre manière moins déterministe. 

Donc, une alternative que je vais parfois utiliser est:

public loaded$: Observable<boolean> = uninitialized('loaded');

uninitialized est défini globalement quelque part comme suit:

export const uninitialized = (name: string) => throwError(name + ' not initialized');

Ensuite, si vous utilisez ce flux sans qu'il soit défini, une erreur d'exécution sera immédiatement générée.

0
Simon_Weaver