Existe-t-il un moyen de vérifier à la fois «null» et «non défini»?

382

Étant donné que TypeScript est fortement typé, il suffit de l'utiliser if () {}pour vérifier nullet undefinedne sonne pas correctement.

TypeScript a-t-il une fonction ou un sucre de syntaxe dédié à cela?

David Liu
la source
9
Since TypeScript is strongly-typedJe n'ai pas trouvé ça dans ses documents et j'ai des doutes à ce sujet ...
pawciobiel
3
Recommande de lire sur les derniers types non nullables, il s'agit de Typescript 2, mais déjà en version bêta à partir d'aujourd'hui. [Types non nullables # 7140] ( github.com/Microsoft/TypeScript/pull/7140 )
RyBolt
2
TypeScript n'a pas de fonctions dédiées pour faire quoi que ce soit. C'est un système de frappe et un transpilateur, pas une bibliothèque.

Réponses:

378

À l'aide d'un test de jonglage, vous pouvez tester les deux nullet undefineden un coup:

if (x == null) {

Si vous utilisez un contrôle strict, il ne sera vrai que pour les valeurs définies sur nullet ne sera pas évalué comme vrai pour les variables non définies:

if (x === null) {

Vous pouvez essayer cela avec différentes valeurs en utilisant cet exemple:

var a: number;
var b: number = null;

function check(x, name) {
    if (x == null) {
        console.log(name + ' == null');
    }

    if (x === null) {
        console.log(name + ' === null');
    }

    if (typeof x === 'undefined') {
        console.log(name + ' is undefined');
    }
}

check(a, 'a');
check(b, 'b');

Production

"a == null"

"a n'est pas défini"

"b == null"

"b === null"

Fenton
la source
52
Qu'est-ce que le "jonglage-chèque"?
kolobok
18
@akapelko c'est là que le type est jonglé (ie "peut-on faire de ce type un booléen"). Ainsi, une chaîne vide est traitée comme un faux booléen, par exemple. Un bug courant lors du jonglage est: "false" == falseune chaîne non vide comme "false" est évaluée true.
Fenton
12
Cela est dû à la «coercition de type» de JS.
Astravagrant
Sauf si x est 0 (et que c'est une valeur valide), il passera votre test non défini / nul.
Jon Gunter
3
@JonGunter ce serait vrai pour les if(x)vérifications de style véridique / falsey , mais non if(x == null), qui ne fait qu'attraper nullet undefined. Vérifiez que var c: number = 0; check(c, 'b');ce n'est pas "nully",, nullou undefined.
Fenton
270
if( value ) {
}

évaluera truesi ce valuen'est pas le cas:

  • null
  • undefined
  • NaN
  • chaîne vide ''
  • 0
  • false

tapuscrit inclut des règles javascript.

Ramazan Sağır
la source
12
Et si la valeur est de type booléen?
ianstigator
pouvez-vous combiner deux variables par exemple. if (value1 && value2) pour vérifier si les deux ne sont pas définis?
ARK
8
@ RamazanSağır ouais merci je le sais, mais le fait est que la valeur 0 est quelque chose de valide que je peux avoir, la seule vérification que je veux faire est que la variable n'est ni nulle ni indéfinie. J'ai lu que je peux le faire en utilisant val! = Null (le! = Au lieu de! == vérifie également la valeur non définie)
Alex
4
Cette solution ne fonctionnera pas si la règle tslint - "strict-boolean-expressions" est activée.
ip_x
1
Il évaluera faux si la valeur nous fausse, aussi simple que cela.
Ayfri
50

TypeScript a-t-il une fonction ou un sucre de syntaxe dédié pour cela?

TypeScript comprend parfaitement la version JavaScript qui est something == null.

TypeScript exclura correctement à la fois nullet undefinedavec de telles vérifications.

Plus

https://basarat.gitbook.io/typescript/recap/null-undefined

basarat
la source
1
J'aime faire deux égaux myVar == null. Juste une autre option.
David Sherret
30
== nullest la bonne façon de tester null & undefined. !!somethingest une contrainte inutile dans un conditionnel en JS (utilisez simplement something). !!somethingcontraindra également 0 et '' à false, ce qui n'est pas ce que vous voulez faire si vous recherchez null / undefined.
C Snover
39

J'ai fait différents tests sur le terrain de jeu dactylographié:

http://www.typescriptlang.org/play/

let a;
let b = null;
let c = "";
var output = "";

if (a == null) output += "a is null or undefined\n";
if (b == null) output += "b is null or undefined\n";
if (c == null) output += "c is null or undefined\n";
if (a != null) output += "a is defined\n";
if (b != null) output += "b is defined\n";
if (c != null) output += "c is defined\n";
if (a) output += "a is defined (2nd method)\n";
if (b) output += "b is defined (2nd method)\n";
if (c) output += "c is defined (2nd method)\n";

console.log(output);

donne:

a is null or undefined
b is null or undefined
c is defined

donc:

  • vérifier si (a == null) a raison de savoir si a est nul ou non défini
  • vérifier si (a! = null) a raison de savoir si a est défini
  • vérifier si (a) est erroné pour savoir si a est défini
Juangui Jordán
la source
1
Pourquoi utiliseriez-vous le terrain de jeu TypeScript pour cela? Rien ici n'a rien à voir avec TypeScript.
10
Parce que la question était liée à Typescript, j'essayais de tester différentes solutions proposées par rapport au transpilateur Typescript.
Juangui Jordán
6
Le transpilateur TS ne transformerait aucun de ces codes.
31

Je pense que cette réponse a besoin d'une mise à jour, consultez l'historique des modifications pour l'ancienne réponse.

Fondamentalement, vous avez trois cas différés nuls, non définis et non déclarés, voir l'extrait ci-dessous.

// bad-file.ts
console.log(message)

Vous obtiendrez une erreur indiquant que la variable messagen'est pas définie (aka non déclarée), bien sûr, le compilateur Typescript ne devrait pas vous permettre de le faire, mais VRAIMENT rien ne peut vous empêcher.

// evil-file.ts
// @ts-gnore
console.log(message)

Le compilateur se contentera de compiler le code ci-dessus. Donc, si vous êtes sûr que toutes les variables sont déclarées, vous pouvez simplement le faire

if ( message != null ) {
    // do something with the message
}

le code ci-dessus vérifiera nullet undefined, MAIS dans le cas où la messagevariable pourrait ne pas être déclarée (par sécurité), vous pouvez considérer le code suivant

if ( typeof(message) !== 'undefined' && message !== null ) {
    // message variable is more than safe to be used.
}

Remarque: l'ordre ici typeof(message) !== 'undefined' && message !== nullest très important, vous devez d'abord vérifier l' undefinedétat, sinon ce sera le même que message != null, merci @Jaider.

Ahmed Kamal
la source
4
M. Kamal si quelque chose = 0, votre vérification avec! Quelque chose vous posera des problèmes.
Justcode
1
@arturios pouvez-vous me donner un exemple !!
Ahmed Kamal
2
@arturios Mais 0 est déjà une valeur fausse en JavaScript !! alors quel est le point ici?
Ahmed Kamal
1
@ Al-un non, voyez-le en action ici
Ahmed Kamal
1
la version mise à jour est incorrecte. La première chose à vérifier ne doit pas être définie ... comme:if(typeof something !== 'undefined' && something !== null){...}
Jaider
27

Dans TypeScript 3.7, nous avons maintenant le chaînage facultatif et la coalescence nulle pour vérifier null et indéfini en même temps, par exemple:

let x = foo?.bar.baz();

ce code vérifiera si foo est défini sinon il retournera non défini

ancienne façon :

if(foo != null && foo != undefined) {
   x = foo.bar.baz();
} 

cette:

let x = (foo === null || foo === undefined) ? undefined : foo.bar();

if (foo && foo.bar && foo.bar.baz) { // ... }

Avec le chaînage optionnel sera:

let x = foo?.bar();

if (foo?.bar?.baz) { // ... }

une autre nouvelle fonctionnalité est Nullish Coalescing , par exemple:

let x = foo ?? bar(); // return foo if it's not null or undefined otherwise calculate bar

ancienne façon:

let x = (foo !== null && foo !== undefined) ?
foo :
bar();
Fateh Mohamed
la source
3
Cela devrait être la réponse acceptée maintenant. Typescript 3.7 prend également en charge "Nullish Coalescing". var foo = possibleUndefinedOrNull ?? fallbackValueIfFirstValueIsUndefinedOrNull; Voici la documentation: typescriptlang.org/docs/handbook/release-notes/…
tkd_aj
23

Vous voudrez peut-être essayer

if(!!someValue)

avec !!.

Explication

Le premier !transformera votre expression en booleanvaleur.

Alors !someValuec'est truesi someValueest faux et falsesi someValuec'est vrai . Cela pourrait prêter à confusion.

En ajoutant un autre !, l'expression est maintenant truesi someValueest vraie et falsesi someValueest fausse , ce qui est beaucoup plus facile à gérer.

Discussion

Maintenant, pourquoi est-ce que je me dérange if (!!someValue)quand quelque chose comme ça if (someValue)m'aurait donné le même résultat?

Parce que !!someValuec'est précisément une expression booléenne, alors qu'elle someValuepourrait être absolument n'importe quoi. Ce type d'expression permettra désormais d'écrire des fonctions (et Dieu nous en avons besoin) comme:

isSomeValueDefined(): boolean {
  return !!someValue
}

au lieu de:

isSomeValueDefined(): boolean {
  if(someValue) {
    return true
  }
  return false
}

J'espère que ça aide.

avi.elkharrat
la source
donc, si someValue est 'false' (avec le type chaîne), alors !! someValue est false (type booléen)?
paul cheung
Je suppose que vous pouvez le dire. Cette technique est précisément utilisée pour éviter ce genre de confusion. J'espère que tu aimes!
avi.elkharrat
mais ce qui m'a dérouté c'est !! 'faux' est vrai. Juste à cause de ce cas, je ne peux pas utiliser cette technique.
paul cheung
!!'false'est en acte truecar 'false'est une chaîne valide
avi.elkharrat
cette technique ne peut donc pas couvrir ce cas, ou existe-t-il une solution de contournement?
paul cheung
16

Car Typescript 2.x.xvous devez le faire de la manière suivante (en utilisant type guard ):

tl; dr

function isDefined<T>(value: T | undefined | null): value is T {
  return <T>value !== undefined && <T>value !== null;
}

Pourquoi?

De cette façon isDefined(), respectera le type de variable et le code suivant saura tenir compte de cette vérification.

Exemple 1 - vérification de base:

function getFoo(foo: string): void { 
  //
}

function getBar(bar: string| undefined) {   
  getFoo(bar); //ERROR: "bar" can be undefined
  if (isDefined(bar)) {
    getFoo(bar); // Ok now, typescript knows that "bar' is defined
  }
}

Exemple 2 - les types respectent:

function getFoo(foo: string): void { 
  //
}

function getBar(bar: number | undefined) {
  getFoo(bar); // ERROR: "number | undefined" is not assignable to "string"
  if (isDefined(bar)) {
    getFoo(bar); // ERROR: "number" is not assignable to "string", but it's ok - we know it's number
  }
}
Sergei Panfilov
la source
14
if(data){}

c'est méchant!

  • nul
  • indéfini
  • faux
  • ....
artemitSoft
la source
2
Et si les données sont de type booléen?
ianstigator
pouvez-vous combiner deux variables par exemple. if (value1 && value2) pour vérifier si les deux ne sont pas définis?
ARK
@ianstigator Un booléen peut être évalué comme trueou falseseulement. Si vous avez un booléen avec une nullaffectation ou une undefinedvaleur, dans les deux cas, la valeur sera évaluée comme false.
KBeDev
5

Si vous utilisez TypeScript, il est préférable de laisser le compilateur rechercher les valeurs nulles et indéfinies (ou la possibilité de celles-ci), plutôt que de les vérifier au moment de l'exécution. (Si vous voulez vérifier au moment de l'exécution, alors comme de nombreuses réponses l'indiquent, utilisez simplementvalue == null ).

Utilisez l'option de compilation strictNullCheckspour indiquer au compilateur d'étouffer les éventuelles valeurs nulles ou non définies. Si vous activez cette option, et puis il y a une situation où vous ne voulez autoriser nulle et non défini, vous pouvez définir le type que Type | null | undefined.


la source
5

Si vous voulez passer tslintsans mettre strict-boolean-expressionsà allow-null-unionou allow-undefined-union, vous devez utiliser isNullOrUndefineddu node« s utilmodule ou rouler votre propre:

// tslint:disable:no-null-keyword
export const isNullOrUndefined =
  <T>(obj: T | null | undefined): obj is null | undefined => {
    return typeof obj === "undefined" || obj === null;
  };
// tslint:enable:no-null-keyword

Pas exactement du sucre syntaxique mais utile lorsque vos règles tslint sont strictes.

Graeme Wicksted
la source
1

Une notation plus rapide et plus courte pour les nullchèques peut être:

value == null ? "UNDEFINED" : value

Cette ligne équivaut à:

if(value == null) {
       console.log("UNDEFINED")
} else {
    console.log(value)
}

Surtout quand vous avez beaucoup de nullcontrôle, c'est une belle notation courte.

Harry Stylesheet
la source
1

J'ai eu ce problème et une partie de la réponse fonctionne très bien pour JSmais pas pour TSici est la raison.

//JS
let couldBeNullOrUndefined;
if(couldBeNullOrUndefined == null) {
  console.log('null OR undefined', couldBeNullOrUndefined);
} else {
  console.log('Has some value', couldBeNullOrUndefined);
}

C'est très bien car JS n'a pas de types

//TS
let couldBeNullOrUndefined?: string | null; // THIS NEEDS TO BE TYPED AS undefined || null || Type(string)

if(couldBeNullOrUndefined === null) { // TS should always use strict-check
  console.log('null OR undefined', couldBeNullOrUndefined);
} else {
  console.log('Has some value', couldBeNullOrUndefined);
}

Dans TS si la variable n'a pas été définie avec nulllorsque vous essayez de vérifier que nullle tslint| le compilateur se plaindra.

//tslint.json
...
"triple-equals":[true],
...
 let couldBeNullOrUndefined?: string; // to fix it add | null

 Types of property 'couldBeNullOrUndefined' are incompatible.
      Type 'string | null' is not assignable to type 'string | undefined'.
        Type 'null' is not assignable to type 'string | undefined'.
T04435
la source
1

Tard pour rejoindre ce fil mais je trouve ce hack JavaScript très pratique pour vérifier si une valeur n'est pas définie

 if(typeof(something) === 'undefined'){
   // Yes this is undefined
 }
Shahid Manzoor Bhat
la source
1

En général , je fais le contrôle de la jonglerie comme Fenton déjà discuté . Pour le rendre plus lisible, vous pouvez utiliser isNil de ramda.

import * as isNil from 'ramda/src/isNil';

totalAmount = isNil(totalAmount ) ? 0 : totalAmount ;
Néo
la source
1

De manière détaillée, si vous souhaitez comparer les valeurs nulles et non définies UNIQUEMENT , utilisez l'exemple de code suivant pour référence:

const incomingValue : string = undefined;
const somethingToCompare : string = incomingValue; // If the line above is not declared, TypeScript will return an excepion

if (somethingToCompare == (undefined || null)) {
  console.log(`Incoming value is: ${somethingToCompare}`);
}

Si incomingValuen'est pas déclaré, TypeScript doit renvoyer une exception. Si cela est déclaré mais non défini, leconsole.log() retourne "La valeur entrante est: non définie". Notez que nous n'utilisons pas l'opérateur strict strict.

La manière "correcte" (vérifiez les autres réponses pour plus de détails), si le incomingValuen'est pas un booleantype, évaluez simplement si sa valeur est vraie, cela sera évalué selon le type de constante / variable. Une truechaîne doit être définie explicitement en tant que chaîne à l'aide de l' = ''affectation. Sinon, il sera évalué comme false. Vérifions ce cas en utilisant le même contexte:

const incomingValue : string = undefined;
const somethingToCompare0 : string = 'Trumpet';
const somethingToCompare1 : string = incomingValue;

if (somethingToCompare0) {
  console.log(`somethingToCompare0 is: ${somethingToCompare0}`); // Will return "somethingToCompare0 is: Trumpet"
}

// Now, we will evaluate the second constant
if (somethingToCompare1) {
  console.log(`somethingToCompare1 is: ${somethingToCompare1}`); // Launched if incomingValue is defined
} else {
  console.log(`somethingToCompare1 is: ${somethingToCompare1}`); // Launched if incomingValue is undefined. Will return "somethingToCompare1 is: undefined"
}
KBeDev
la source
somethingToCompare == (non défini || null). (undefined || null) se résout en null, c'est donc une comparaison
approximative
@carlosvini Bien sûr, le point de comparaison est d'être verbeux et de fournir un code de référence. C'est la raison de la comparaison d'égalité non stricte. Le but de la réponse est d'être clair et explicatif. Je vais modifier le texte pour éviter toute confusion
KBeDev
0

vous pouvez utiliser

if(x === undefined)
akshay reddy
la source
0

Tout,

La réponse avec le plus de votes ne fonctionne pas vraiment si vous travaillez avec un objet. Dans ce cas, si une propriété n'est pas présente, le chèque ne fonctionnera pas. Et c'était le problème dans notre cas: voir cet exemple:

var x =
{ name: "Homer", LastName: "Simpson" };

var y =
{ name: "Marge"} ;

var z =
{ name: "Bart" , LastName: undefined} ;

var a =
{ name: "Lisa" , LastName: ""} ;

var hasLastNameX = x.LastName != null;
var hasLastNameY = y.LastName != null;
var hasLastNameZ = z.LastName != null;
var hasLastNameA = a.LastName != null;



alert (hasLastNameX + ' ' + hasLastNameY + ' ' + hasLastNameZ + ' ' + hasLastNameA);

var hasLastNameXX = x.LastName !== null;
var hasLastNameYY = y.LastName !== null;
var hasLastNameZZ = z.LastName !== null;
var hasLastNameAA = a.LastName !== null;

alert (hasLastNameXX + ' ' + hasLastNameYY + ' ' + hasLastNameZZ + ' ' + hasLastNameAA);

Résultat:

true , false, false , true (in case of !=)
true , true, true, true (in case of !==) => so in this sample not the correct answer

lien plunkr: https://plnkr.co/edit/BJpVHD95FhKlpHp1skUE

Ben Croughs
la source
Ce n'est pas un bon test. Aucune de ces valeurs n'est strictement null . Essayez ceci: plnkr.co/edit/NfiVnQNes1p8PvXd1fCG?p=preview
simonhamp
0

Puisque TypeScript est un sur-ensemble typé de JavaScript ES6. Et lodash est une bibliothèque de javascript.

L'utilisation de lodash pour vérifier si la valeur est nulle ou non définie peut être effectuée à l'aide de _.isNil().

_.isNil(value)

Arguments

valeur (*): La valeur à vérifier.

Retour

(booléen) : retourne vrai si la valeur est nulle, sinon faux.

Exemple

_.isNil(null);
// => true

_.isNil(void 0);
// => true

_.isNil(NaN);
// => false

Lien

Lodash Docs

7e2e63de
la source
1
Pourquoi cette méthode vaut -2? Lodash n'est pas bon avec le script de type?
Thomas Poignant
0

attention si vous utilisez le stockage local, vous pouvez vous retrouver avec la chaîne non définie plutôt que la valeur non définie:

localStorage.setItem('mykey',JSON.stringify(undefined));
localStorage.getItem('mykey') === "undefined"
true

Les gens peuvent trouver cela utile: https://github.com/angular/components/blob/master/src/cdk/coercion/boolean-property.spec.ts

/**
 * @license
 * Copyright Google LLC All Rights Reserved.
 *
 * Use of this source code is governed by an MIT-style license that can be
 * found in the LICENSE file at https://angular.io/license
 */

/** Coerces a data-bound value (typically a string) to a boolean. */
export function coerceBooleanProperty(value: any): boolean {
  return value != null && `${value}` !== 'false';
}

import {coerceBooleanProperty} from './boolean-property';

describe('coerceBooleanProperty', () => {

  it('should coerce undefined to false', () => {
    expect(coerceBooleanProperty(undefined)).toBe(false);
  });

  it('should coerce null to false', () => {
    expect(coerceBooleanProperty(null)).toBe(false);
  });

  it('should coerce the empty string to true', () => {
    expect(coerceBooleanProperty('')).toBe(true);
  });

  it('should coerce zero to true', () => {
    expect(coerceBooleanProperty(0)).toBe(true);
  });

  it('should coerce the string "false" to false', () => {
    expect(coerceBooleanProperty('false')).toBe(false);
  });

  it('should coerce the boolean false to false', () => {
    expect(coerceBooleanProperty(false)).toBe(false);
  });

  it('should coerce the boolean true to true', () => {
    expect(coerceBooleanProperty(true)).toBe(true);
  });

  it('should coerce the string "true" to true', () => {
    expect(coerceBooleanProperty('true')).toBe(true);
  });

  it('should coerce an arbitrary string to true', () => {
    expect(coerceBooleanProperty('pink')).toBe(true);
  });

  it('should coerce an object to true', () => {
    expect(coerceBooleanProperty({})).toBe(true);
  });

  it('should coerce an array to true', () => {
    expect(coerceBooleanProperty([])).toBe(true);
  });
});
Robert King
la source
-4

Je l'écris toujours comme ceci:

var foo:string;

if(!foo){
   foo="something";    
}

Cela fonctionnera bien et je pense que c'est très lisible.

AlexB
la source
21
Ne fonctionnerait pas pour les nombres car 0réussit également le !footest.
Hasen
10
Ne fonctionne pas non plus pour les booléens, où undefinedest différent de false. Ceci est très courant avec les paramètres de fonction booléenne facultatifs, où vous devez utiliser l'approche JavaScript commune:function fn(flag?: boolean) { if (typeof flag === "undefined") flag = true; /* set default value */ }
Gingi
Semble ok travail pour booléens: var isTrue; if(isTrue)//skips, if(!isTrue)// enters if(isTrue === undefined)//enters. A également essayé en tapant avecvar isTrue:boolean lequel n'était pas défini, et la même chose si vérifie. @ Gingi, y a-t-il quelque chose de différent dans ce que tu as essayé et ce que j'ai essayé?
Drenai