Existe uma maneira de verificar se há `null` e` undefined`?

382

Como o TypeScript é fortemente digitado, basta usar if () {}para verificar nulle undefinednão parece certo.

O TypeScript tem alguma função dedicada ou açúcar de sintaxe para isso?

David Liu
fonte
9
Since TypeScript is strongly-typedEu não poderia encontrar este em sua docs e não tenho dúvidas sobre isso ...
pawciobiel
3
Recomenda-se ler sobre os tipos não anuláveis ​​mais recentes, este é o TypeScript 2, mas já está na versão beta a partir de hoje. [Tipos não anuláveis ​​# 7140] ( github.com/Microsoft/TypeScript/pull/7140 )
RyBolt 5/16
2
O TypeScript não possui funções dedicadas para fazer qualquer coisa. É um sistema de digitação e um transpiler, não uma biblioteca.

Respostas:

378

Usando uma verificação de malabarismo, você pode testar ambos nulle undefinedem um hit:

if (x == null) {

Se você usar uma verificação estrita, isso só será verdadeiro para valores definidos como nulle não será avaliado como verdadeiro para variáveis ​​indefinidas:

if (x === null) {

Você pode tentar isso com vários valores usando este exemplo:

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

Resultado

"a == null"

"a é indefinido"

"b == null"

"b === null"

Fenton
fonte
52
O que é "verificação de malabarismo"?
Kolobok
18
@akapelko é onde o tipo é manipulado (ou seja, "podemos tornar esse tipo um booleano"). Portanto, uma cadeia vazia é tratada como um falso booleano, por exemplo. Um erro comum ao manipular é: "false" == falseuma string não vazia como "false" é avaliada como true.
Fenton
12
Isso se deve à 'coerção de tipo' do JS.
precisa saber é o seguinte
Exceto se x for 0 (e esse é um valor válido), ele passará no teste indefinido / nulo.
Jon Gunter
3
@ JonGunter isso seria verdade nas if(x)verificações de estilo truthy / falsey , mas não if(x == null), que apenas capturam nulle undefined. Verifique se var c: number = 0; check(c, 'b');não está "nulo" null, ou undefined.
Fenton
269
if( value ) {
}

avaliará truese valuenão é:

  • null
  • undefined
  • NaN
  • seqüência vazia ''
  • 0
  • false

O texto datilografado inclui regras javascript.

Ramazan Sağır
fonte
12
E se o valor for do tipo booleano?
Ianstigator 6/10
você pode combinar duas variáveis, por exemplo. if (value1 && value2) para verificar se os dois estão indefinidos?
ARK
8
@ RamazanSağır yeah obrigado Eu sei disso, mas o fato é que o valor 0 é algo válido que eu posso ter, a única verificação que quero fazer é que a variável não seja nula ou indefinida. Eu li que eu posso fazer isso usando val = null (a = em vez de == também verificações de valor indefinido!)!
Alex
4
Esta solução não funcionará se a regra tslint - "strict-boolean-expression" estiver ativada.
Ip_x 24/09/19
11
Ele avaliará falso se nos valorizar falso, tão simples quanto isso.
Ayfri 18/04
50

O TypeScript possui função dedicada ou açúcar de sintaxe para este

O TypeScript entende completamente a versão do JavaScript que é something == null.

O TypeScript descartará corretamente ambos nulle undefinedcom essas verificações.

Mais

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

basarat
fonte
11
Eu gosto de fazer dois iguais myVar == null. Apenas outra opção.
David Sherret 11/03/2015
30
== nullé a maneira correta de testar nulos e indefinidos. !!somethingé uma coerção inútil em um condicional em JS (apenas use something). !!somethingtambém coagirá 0 e '' a falso, o que não é o que você deseja fazer se estiver procurando por nulo / indefinido.
C # Snover
39

Eu fiz testes diferentes no playground tipográfico:

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

dá:

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

tão:

  • verificar se (a == null) está certo em saber se a é nulo ou indefinido
  • verificando se (a! = null) está certo em saber se a está definido
  • verificar se (a) está errado para saber se a está definido
Juangui Jordán
fonte
11
Por que você usaria o playground TypeScript para isso? Nada aqui tem algo a ver com o TypeScript.
10
Como a pergunta estava relacionada ao Typescript, eu estava tentando testar diferentes soluções propostas em relação ao transpilador Typescript.
Juangui Jordán
6
O transpiler TS não transformaria nada desse código.
31

Acho que esta resposta precisa de uma atualização, verifique o histórico de edições para obter a resposta antiga.

Basicamente, você tem três casos diferidos nulos, indefinidos e não declarados, consulte o trecho abaixo.

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

Você receberá um erro dizendo que a variável messageé indefinida (também não declarada); é claro, o compilador Typescript não deve permitir que você faça isso, mas REALMENTE nada pode impedi-lo.

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

O compilador terá prazer em compilar apenas o código acima. Portanto, se você tiver certeza de que todas as variáveis ​​são declaradas, basta fazer isso

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

o código acima procurará nulle undefined, MAS, caso a messagevariável não seja declarada (por segurança), considere o código a seguir

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

Nota: a ordem aqui typeof(message) !== 'undefined' && message !== nullé muito importante, você deve verificar undefinedprimeiro o estado; caso contrário, será o mesmo que message != null, graças a @Jaider.

Ahmed Kamal
fonte
4
M. Kamal se algo = 0, sua verificação com! Algo lhe dará problemas.
Justcode #
11
@arturios você pode me dar um exemplo !!
Ahmed Kamal
2
@arturios Mas 0 já é um valor falso em JavaScript !! então qual é o ponto aqui?
Ahmed Kamal
11
@ Al-un não, vê-lo em ação aqui
Ahmed Kamal
11
a versão atualizada está errada. A primeira coisa a verificação deve ser indefinido ... como:if(typeof something !== 'undefined' && something !== null){...}
Jaider
27

No TypeScript 3.7 , agora temos encadeamento opcional e coalescência nula para verificar nulo e indefinido ao mesmo tempo, por exemplo:

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

este código irá verificar se foo está definido, caso contrário ele retornará indefinido

maneira antiga :

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

isto:

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

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

Com encadeamento opcional será:

let x = foo?.bar();

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

outro novo recurso é o Nullish Coalescing , por exemplo:

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

à moda antiga:

let x = (foo !== null && foo !== undefined) ?
foo :
bar();
Fateh Mohamed
fonte
3
Essa deve ser a resposta aceita agora. O Typecript 3.7 também suporta "Nullish Coalescing". var foo = possibleUndefinedOrNull ?? fallbackValueIfFirstValueIsUndefinedOrNull; Aqui está a documentação: typescriptlang.org/docs/handbook/release-notes/…
tkd_aj
23

Você pode tentar

if(!!someValue)

com !!.

Explicação

O primeiro !transformará sua expressão em um booleanvalor.

Então !someValueé truese someValueé falso e falsese someValueé verdade . Isso pode ser confuso.

Ao adicionar uma outra !, a expressão agora é truese someValueé truthy e falsese someValueé Falsas , que é muito mais fácil de gerir.

Discussão

Agora, por que me incomodo if (!!someValue)quando algo assim if (someValue)me daria o mesmo resultado?

Porque !!someValueé precisamente uma expressão booleana, enquanto que someValuepode ser absolutamente qualquer coisa. Esse tipo de expressão agora permitirá escrever funções (e Deus precisamos delas) como:

isSomeValueDefined(): boolean {
  return !!someValue
}

ao invés de:

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

Espero que ajude.

avi.elkharrat
fonte
então, se someValue for 'false' (com o tipo string), então !! someValue é false (tipo booleano)?
paul cheung
Acho que você pode dizer isso. Essa técnica é usada com precisão para evitar esse tipo de confusão. Espero que você goste!
avi.elkharrat 12/02/19
mas o que me confundiu é !! 'falso' é igual a verdadeiro. Só por causa deste caso, não posso usar esta técnica.
paul cheung
!!'false'está em ação trueporque 'false'é uma sequência válida
avi.elkharrat 12/02/19
portanto, essa técnica não pode cobrir esse caso ou existe uma solução alternativa?
paul cheung
16

Para Typescript 2.x.xvocê deve fazê-lo da seguinte maneira (usando tipo guarda ):

tl; dr

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

Por quê?

Dessa forma isDefined(), respeitará o tipo de variável e o código a seguir saberá levar essa conta em consideração.

Exemplo 1 - verificação 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
  }
}

Exemplo 2 - os tipos respeitam:

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

é mau! dados

  • nulo
  • Indefinido
  • falso
  • ....
artemitSoft
fonte
2
E se os dados forem do tipo booleano?
Ianstigator
você pode combinar duas variáveis, por exemplo. if (value1 && value2) para verificar se os dois estão indefinidos?
ARK
@ianstigator Um booleano pode ser avaliado como trueou falseapenas. Se você tiver um booleano com uma nullatribuição ou um undefinedvalor, em ambos os casos, o valor será avaliado como false.
KBeDev
5

Se você estiver usando o TypeScript, é uma abordagem melhor permitir que o compilador verifique nulos e indefinidos (ou a possibilidade deles), em vez de procurá-los em tempo de execução. (Se você deseja verificar em tempo de execução, o número de respostas indicado, basta usar value == null).

Use a opção de compilação strictNullCheckspara dizer ao compilador para engasgar com possíveis valores nulos ou indefinidos. Se você definir essa opção, e depois há uma situação onde você não deseja permitir nulos e indefinidos, você pode definir o tipo Type | null | undefined.


fonte
5

Se você quer passar tslintsem definir strict-boolean-expressionsa allow-null-unionou allow-undefined-union, você precisa usar isNullOrUndefineda partir nodedo utilmódulo ou rolar o seu próprio:

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

Não é exatamente um açúcar sintático, mas útil quando suas regras de tslint são rigorosas.

Graeme Wicksted
fonte
1

Uma notação mais rápida e mais curta para nullverificações pode ser:

value == null ? "UNDEFINED" : value

Esta linha é equivalente a:

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

Especialmente quando você tem muito nullcheque, é uma notação curta e agradável.

Harry Stylesheet
fonte
1

Eu tive esse problema e algumas das respostas funcionam muito bem, JSmas não por TSaqui é o motivo.

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

Tudo isso é bom, já que JS não tem 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);
}

Em TS, se a variável não foi definida nullquando você tenta verificar se nullo tslint| compilador irá reclamar.

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

Tarde para ingressar neste segmento, mas acho esse hack JavaScript muito útil para verificar se um valor é indefinido

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

Normalmente, faço o malabarismo como Fenton já discutiu . Para torná-lo mais legível, você pode usar o isNil do ramda.

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

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

Como uma maneira detalhada, se você deseja comparar SOMENTE valores nulos e indefinidos , use o seguinte código de exemplo para referência:

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

Se incomingValuenão for declarado, o TypeScript deve retornar uma exceção. Se isso for declarado, mas não definido, console.log()retornará "O valor recebido é: indefinido". Observe que não estamos usando o operador estrito igual.

A maneira "correta" (verifique as outras respostas para obter detalhes), se incomingValuenão for um booleantipo, basta avaliar se seu valor é verdadeiro, isso será avaliado de acordo com o tipo de constante / variável. Uma truestring deve ser definida explicitamente como string usando a = ''atribuição. Caso contrário, será avaliado como false. Vamos verificar este caso usando o mesmo 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
fonte
somethingToCompare == (indefinido || nulo). (undefined || null) resolve como null, portanto é uma comparação frouxa entre somethingToCompare e null
carlosvini
@carlosvini Claro, o objetivo da comparação é ser detalhado e fornecer um código de referência. Essa é a razão da comparação igual a não-estrita. O objetivo da resposta é ser claro e explicativo. Vou editar o texto para evitar confusão
KBeDev
0

você pode usar

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

Todos,

A resposta com mais votos não funciona realmente se você estiver trabalhando com um objeto. Nesse caso, se uma propriedade não estiver presente, a verificação não funcionará. E esse foi o problema no nosso caso: veja este exemplo:

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

Resultado:

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

Link do plunkr: https://plnkr.co/edit/BJpVHD95FhKlpHp1skUE

Ben Croughs
fonte
Este não é um bom teste. Nenhum desses valores é estritamente null . Tente isso: plnkr.co/edit/NfiVnQNes1p8PvXd1fCG?p=preview
simonhamp
0

Como o TypeScript é um superconjunto digitado do JavaScript ES6. E o lodash é uma biblioteca de javascript.

O uso do lodash para verificar se o valor é nulo ou indefinido pode ser feito usando _.isNil().

_.isNil(value)

Argumentos

valor (*): o valor a ser verificado.

Devoluções

(booleano) : retorna true se o valor for nulo, caso contrário, false.

Exemplo

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

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

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

Ligação

Lodash Docs

7e2e63de
fonte
11
Por que este método é -2? Lodash não é bom com script de tipo?
Thomas Poignant
0

cuidado se estiver usando armazenamento local, você pode acabar com a sequência indefinida em vez do valor indefinido:

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

As pessoas podem achar isso ú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
fonte
-4

Eu sempre escrevo assim:

var foo:string;

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

Isso vai funcionar bem e eu acho que é muito legível.

AlexB
fonte
21
Não funcionaria para números, porque 0também passa no !footeste.
hasen
10
Também não funciona para booleanos, onde undefinedé diferente de false. Isso é muito comum nos parâmetros opcionais da função booleana, nos quais você deve usar a abordagem comum do JavaScript:function fn(flag?: boolean) { if (typeof flag === "undefined") flag = true; /* set default value */ }
Gingi 27/05
Parece ok trabalho para booleans: var isTrue; if(isTrue)//skips, if(!isTrue)// enters if(isTrue === undefined)//enters. Também tentei em texto datilografado com o var isTrue:booleanqual era indefinido, e o mesmo se verifica. @ Gingi, há algo diferente sobre o que você tentou e o que eu tentei?
Drenai 7/08/16