¿Hay alguna manera de verificar tanto `null` como` undefined`?

382

Dado que TypeScript está fuertemente tipado, simplemente se usa if () {}para verificar nully undefinedno suena bien.

¿TypeScript tiene alguna función dedicada o sintaxis de azúcar para esto?

David Liu
fuente
99
Since TypeScript is strongly-typedNo pude encontrar esto en él de documentos y no tengo dudas al respecto ...
pawciobiel
3
Recomiendo leer sobre los últimos tipos no anulables, este es Tiposcriptcript 2, pero ya está en versión beta a partir de hoy. [Tipos no anulables # 7140] ( github.com/Microsoft/TypeScript/pull/7140 )
RyBolt
2
TypeScript no tiene funciones dedicadas para hacer nada. Es un sistema de mecanografía y un transpilador, no una biblioteca.

Respuestas:

378

Usando un chequeo de malabarismo, puede probar ambos nully undefinedde una sola vez:

if (x == null) {

Si usa una verificación estricta, solo será cierto para los valores establecidos en nully no se evaluará como verdadero para las variables indefinidas:

if (x === null) {

Puedes probar esto con varios valores usando este ejemplo:

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');

Salida

"a == nulo"

"a no está definido"

"b == nulo"

"b === nulo"

Fenton
fuente
52
¿Qué es "chequeo de malabarismo"?
kolobok
18
@akapelko es donde se hace malabares con el tipo (es decir, "podemos hacer que este tipo sea booleano"). Por lo tanto, una cadena vacía se trata como un falso booleano, por ejemplo. Un error común al hacer malabares es: "false" == falseuna cadena no vacía como "falso" se evalúa true.
Fenton
12
Esto se debe a la "coerción de tipo" de JS.
Astravagrant
Excepto si x es 0 (y ese es un valor válido), pasará su prueba indefinida / nula.
Jon Gunter
3
@JonGunter eso sería cierto para las comprobaciones de if(x)estilo verdadero / falso , pero no if(x == null), que solo atrapa nully undefined. Verifíquelo usando var c: number = 0; check(c, 'b');no es "nully" null, o undefined.
Fenton
270
if( value ) {
}

evaluará truesi valueno es:

  • null
  • undefined
  • NaN
  • cuerda vacía ''
  • 0
  • false

El mecanografiado incluye reglas de JavaScript.

Ramazan Sağır
fuente
12
¿Qué pasa si el valor es de tipo booleano?
ianstigator
¿Se pueden combinar dos variables, por ejemplo. if (value1 && value2) para verificar si ambos están indefinidos?
ARCA
8
@ RamazanSağır sí, gracias, lo sé, pero el hecho de que el valor 0 es algo válido que puedo tener, lo único que quiero hacer es que la variable no sea nula o indefinida. He leído que puedo hacerlo usando val! = Null (el! = En lugar de! == también verifica el valor indefinido)
Alex
44
Esta solución no funcionará si la regla tslint - "estrictas-expresiones-booleanas" está habilitada.
ip_x
1
Evaluará falso si nos valora falso, tan simple como esto.
Ayfri
50

¿TypeScript tiene una función dedicada o sintaxis de azúcar para esto?

TypeScript comprende completamente la versión de JavaScript que es something == null.

TypeScript descartará correctamente ambos nully undefinedcon tales comprobaciones.

Más

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

basarat
fuente
1
Me gusta hacer dos iguales myVar == null. Solo otra opción.
David Sherret
30
== nulles la forma correcta de probar nulo e indefinido. !!somethinges una coerción inútil en un condicional en JS (solo uso something). !!somethingtambién obligará a 0 y '' a falso, que no es lo que desea hacer si está buscando nulo / indefinido.
C Snover
39

Hice diferentes pruebas en el patio de juegos mecanografiado:

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

da:

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

entonces:

  • comprobar si (a == nulo) es correcto para saber si a es nulo o indefinido
  • comprobar si (a! = null) es correcto para saber si se define a
  • comprobar si (a) es incorrecto para saber si se define a
Juangui Jordán
fuente
1
¿Por qué usarías el campo de juegos TypeScript para esto? Nada aquí tiene nada que ver con TypeScript.
10
Debido a que la pregunta estaba relacionada con el mecanografiado, estaba tratando de probar diferentes soluciones propuestas contra el transpilador mecanografiado.
Juangui Jordán
66
El transpilador TS no transformaría nada de este código.
31

Creo que esta respuesta necesita una actualización, consulte el historial de edición de la respuesta anterior.

Básicamente, tiene tres casos deferentes nulos, indefinidos y no declarados, vea el fragmento a continuación.

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

Obtendrá un error que dice que la variable messageno está definida (también conocida como no declarada), por supuesto, el compilador de Script no debería permitirle hacer eso, pero REALMENTE nada puede impedirlo.

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

El compilador estará encantado de compilar el código anterior. Entonces, si está seguro de que todas las variables están declaradas, simplemente puede hacerlo

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

el código anterior verificará nully undefined, PERO en caso de que la messagevariable no esté declarada (por seguridad), puede considerar el siguiente código

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

Nota: el pedido aquí typeof(message) !== 'undefined' && message !== nulles muy importante, undefinedprimero debe verificar el estado, de lo contrario será el mismo que message != null, gracias @Jaider.

Ahmed Kamal
fuente
44
M. Kamal si algo = 0, su verificación con! Algo le dará problemas.
justcode
1
@arturios puedes darme un ejemplo !!
Ahmed Kamal
2
@arturios ¡Pero 0 ya es un valor falso en JavaScript! Entonces, ¿cuál es el punto aquí?
Ahmed Kamal
1
@ Al-un no, míralo en acción aquí
Ahmed Kamal
1
La versión actualizada es incorrecta. Lo primero que debe verificar no debe estar definido ... como:if(typeof something !== 'undefined' && something !== null){...}
Jaider
27

En TypeScript 3.7 ahora tenemos encadenamiento opcional y fusión nula para verificar nulos e indefinidos al mismo tiempo, por ejemplo:

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

este código verificará si foo está definido; de lo contrario, volverá indefinido

antigua manera :

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

esta:

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

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

Con encadenamiento opcional será:

let x = foo?.bar();

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

Otra característica nueva es Nullish Coalescing , por ejemplo:

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

vieja forma:

let x = (foo !== null && foo !== undefined) ?
foo :
bar();
Fateh Mohamed
fuente
3
Esta debería ser la respuesta aceptada ahora. El mecanografiado 3.7 también es compatible con "Nullish Coalescing". var foo = possibleUndefinedOrNull ?? fallbackValueIfFirstValueIsUndefinedOrNull; Aquí está la documentación: typescriptlang.org/docs/handbook/release-notes/…
tkd_aj
23

Es posible que desee probar

if(!!someValue)

con !!.

Explicación

El primero !convertirá tu expresión en un booleanvalor.

Entonces !someValuees truesi someValuees falso y falsesi someValuees verdadero . Esto puede ser confuso.

Al agregar otro !, la expresión ahora es truesi someValuees verdadero y falsesi someValuees falso , lo cual es mucho más fácil de administrar.

Discusión

Ahora, ¿por qué me molesto if (!!someValue)cuando algo así if (someValue)me hubiera dado el mismo resultado?

Porque !!someValuees precisamente una expresión booleana, mientras que someValuepodría ser absolutamente cualquier cosa. Este tipo de expresión ahora permitirá escribir funciones (y Dios las necesitamos) como:

isSomeValueDefined(): boolean {
  return !!someValue
}

en vez de:

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

Espero que ayude.

avi.elkharrat
fuente
entonces, si someValue es 'falso' (con tipo de cadena), entonces someValue es falso (tipo booleano)?
Paul Cheung
Supongo que puede decirlo. Esta técnica se utiliza precisamente para evitar tener este tipo de confusión. ¡Espero que te guste!
avi.elkharrat
pero lo que me confundió es !! 'falso' es igual a verdadero. Solo por este caso, no puedo usar esta técnica.
Paul Cheung
!!'false'está hecho trueporque 'false'es una cadena válida
avi.elkharrat
entonces esta técnica no puede cubrir este caso, ¿o hay una solución alternativa?
Paul Cheung
16

Para ello Typescript 2.x.x, debe hacerlo de la siguiente manera (usando type guard ):

tl; dr

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

¿Por qué?

De esta forma isDefined()se respetará el tipo de variable y el siguiente código sabría tener en cuenta este cheque.

Ejemplo 1 - verificación básica:

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

Ejemplo 2 - respeto de tipos:

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
fuente
14
if(data){}

es malo! datos

  • nulo
  • indefinido
  • falso
  • ....
artemitSoft
fuente
2
¿Y si los datos son de tipo booleano?
ianstigator
¿Se pueden combinar dos variables, por ejemplo. if (value1 && value2) para verificar si ambos están indefinidos?
ARCA
@ianstigator Un booleano se puede evaluar como trueo falsesolo. Si tiene un valor booleano con una nullasignación o un undefinedvalor, en ambos casos el valor se evaluará como false.
KBeDev
5

Si está utilizando TypeScript, es un mejor enfoque dejar que el compilador verifique si hay valores nulos e indefinidos (o la posibilidad de que existan), en lugar de verificarlos en tiempo de ejecución. (Si desea verificar en tiempo de ejecución, entonces, como indican muchas respuestas, simplemente use value == null).

Use la opción de compilación strictNullCheckspara indicarle al compilador que se asfixie ante posibles valores nulos o indefinidos. Si se establece esta opción, y luego hay una situación en la que no desea permitir nula y sin definir, se puede definir el tipo Type | null | undefined.


fuente
5

Si desea pasar tslintsin fijar strict-boolean-expressionsa allow-null-uniono allow-undefined-union, es necesario el uso isNullOrUndefinedde node's utilmódulo o hágalo usted mismo:

// 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

No es exactamente el azúcar sintáctico, pero es útil cuando las reglas de tslint son estrictas.

Graeme Wicksted
fuente
1

Una notación más rápida y más corta para los nullcontroles puede ser:

value == null ? "UNDEFINED" : value

Esta línea es equivalente a:

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

Especialmente cuando tienes mucho nullcheque, es una buena notación corta.

Harry Stylesheet
fuente
1

Tuve este problema y algunas de las respuestas funcionan bien, JSpero esta TSes la razón.

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

Eso es todo bueno ya que JS no tiene tipos

//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);
}

En TS si la variable no se definió con nullcuando intenta comprobar que nullel tslint| El compilador se quejará.

//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
fuente
1

Tarde para unirse a este hilo, pero encuentro este truco de JavaScript muy útil para verificar si un valor no está definido

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

Por lo general, hago el control de malabarismo como Fenton ya discutió . Para que sea más fácil de leer, puede utilizar isNil de Ramda.

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

totalAmount = isNil(totalAmount ) ? 0 : totalAmount ;
Neo
fuente
1

Como forma detallada, si desea comparar valores nulos e indefinidos SOLAMENTE , use el siguiente código de ejemplo como referencia:

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 incomingValue no se declara, TypeScript debería devolver una excepción. Si esto se declara pero no se define, console.log()devolverá "El valor entrante es: indefinido". Tenga en cuenta que no estamos utilizando el operador estricto igual.

La forma "correcta" (verifique las otras respuestas para más detalles), si el incomingValueno es un booleantipo, simplemente evalúe si su valor es verdadero, esto se evaluará de acuerdo con el tipo constante / variable. Una truecadena debe definirse explícitamente como una cadena que utiliza la = ''asignación. Si no, se evaluará como false. Verifiquemos este caso usando el mismo contexto:

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
fuente
somethingToCompare == (indefinido || nulo). (undefined || null) se resuelve en nulo, por lo que es una comparación floja entre somethingToCompare y null
carlosvini
@carlosvini Claro, el punto de la comparación es ser detallado y proporcionar un código de referencia. Esa es la razón de la comparación de igualdad no estricta. El propósito de la respuesta es ser claro y explicativo.
Editaré
0

puedes usar

if(x === undefined)
akshay reddy
fuente
0

Todas,

La respuesta con más votos no funciona realmente si está trabajando con un objeto. En ese caso, si una propiedad no está presente, el cheque no funcionará. Y ese fue el problema en nuestro caso: vea esta muestra:

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

Salir:

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

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

Ben Croughs
fuente
Esta no es una buena prueba. Ninguno de esos valores es estrictamente null . Pruebe esto: plnkr.co/edit/NfiVnQNes1p8PvXd1fCG?p=preview
simonhamp
0

Dado que TypeScript es un superconjunto mecanografiado de ES6 JavaScript. Y lodash son una biblioteca de javascript.

El uso de lodash para verificar si el valor es nulo o indefinido se puede hacer usando _.isNil().

_.isNil(value)

Argumentos

valor (*): El valor a verificar.

Devoluciones

(booleano) : devuelve verdadero si el valor es nulo, de lo contrario falso.

Ejemplo

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

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

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

Enlace

Docs Lodash

7e2e63de
fuente
1
¿Por qué este método son -2? Lodash no es bueno con el script de tipo?
Thomas Poignant
0

Tenga cuidado si está usando almacenamiento local, puede terminar con la cadena indefinida en lugar del valor indefinido:

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

La gente puede encontrar esto útil: 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
fuente
-4

Siempre lo escribo así:

var foo:string;

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

Esto funcionará bien y creo que es muy legible.

AlexB
fuente
21
No funcionaría para los números porque 0también pasa la !fooprueba.
Hasen
10
Tampoco funciona para booleanos, donde undefinedes diferente de false. Esto es muy común con los parámetros opcionales de la función booleana, donde debe usar el enfoque común de JavaScript:function fn(flag?: boolean) { if (typeof flag === "undefined") flag = true; /* set default value */ }
Gingi
Parece bien el trabajo de los booleanos: var isTrue; if(isTrue)//skips, if(!isTrue)// enters if(isTrue === undefined)//enters. También lo probé en mecanografiado con el var isTrue:booleanque no estaba definido, y lo mismo si se comprueba. @Gingi, ¿hay algo diferente en lo que intentaste y en lo que yo probé?
Drenai