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?
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")
};
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;
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.
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.
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;
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.
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' }] });
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
}
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.
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');
Où 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.