有没有办法检查`null`和`undefined`?


381

由于TypeScript是强类型的,因此仅if () {}用于检查nullundefined听起来不正确。

TypeScript是否为此具有任何专用功能或语法糖?


9
Since TypeScript is strongly-typed我在文档中找不到这个,对此我也有疑问……
pawciobiel 2015年

3
建议阅读最新的非null类型,这是Typescript 2,但截至目前已经处于beta中。[不可为空的类型#7140](github.com/Microsoft/TypeScript/pull/7140
RyBolt

2
TypeScript没有专用的功能来执行任何操作。它是一个打字系统和一个翻译器,而不是一个库。

Answers:


378

使用杂耍检查,你可以测试nullundefined一重击:

if (x == null) {

如果使用严格检查,则仅对于设置为的值null将为true,而对于未定义的变量将为true:

if (x === null) {

您可以使用以下示例尝试各种值:

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

输出量

“一个==空”

“一个未定义”

“ b == null”

“ b === null”


52
什么是“杂耍检查”?
kolobok '16

18
@akapelko就是在这里处理类型的地方(即“我们可以将此类型设为布尔值”)吗?因此,例如,将空字符串视为布尔假值。杂耍时的一个常见错误是:"false" == false像“ false”这样的非空字符串的求值为true
芬顿

12
这是由于JS的“类型强制”。
Astravagrant

除非x为0(这是一个有效值),否则它将通过您的未定义/空测试。
乔恩·冈特

3
@JonGunter在true / falsey if(x)样式检查中正确,但不是if(x == null),仅捕获nullundefined。使用var c: number = 0; check(c, 'b');“ nully” null,或来检查它undefined
Fenton

268
if( value ) {
}

将评估true是否value为:

  • null
  • undefined
  • NaN
  • 空字符串 ''
  • 0
  • false

打字稿包含javascript规则。


12
如果值是布尔类型怎么办?
ianstigator

你可以结合两个变量,例如。if(value1 && value2)检查它们是否都未定义?
ARK

8
@RamazanSağır是的,我知道,但是事实是0值是我可以拥有的有效值,我要做的唯一检查是变量既不为null也不未定义。我已经读过我可以通过使用val!= null(用!=代替!==来检查未定义的值)来做到这一点
Alex

4
如果启用了tslint规则-“ strict-boolean-expressions”,则此解决方案将不起作用。
ip_x

1
如果我们虚假评估,它将评估为false,如此简单。
Ayfri

50

TypeScript是否为此具有专用功能或语法糖

TypeScript完全了解JavaScript版本something == null

TypeScript将正确排除这两个方面nullundefined进行此类检查。

更多

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


1
我喜欢两个平等myVar == null。只是另一个选择。
David Sherret'3

30
== null是测试null和undefined的正确方法。!!something是JS中有条件的强制使用(只是使用something)。!!something还将0和''强制转换为false,如果您要查找null / undefined,这不是您想要的。
C Snover 2015年

39

我在打字稿游乐场进行了不同的测试:

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

给出:

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

所以:

  • 检查(a == null)是否正确以知道a为null还是未定义
  • 检查(a!= null)是否正确以了解是否已定义a
  • 检查(a)是否错误以知道是否已定义a

1
为什么要为此使用TypeScript游乐场?这里与TypeScript没有任何关系。

10
因为问题与Typescript有关,所以我试图针对Typescript编译器测试不同的建议解决方案。
JuanguiJordán17年

6
TS编译器根本不会转换任何此代码。

31

我认为该答案需要更新,请检查旧答案的编辑历史记录。

基本上,您有三种不同的情况:null,undefined和unclared,请参见下面的代码段。

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

您会收到一条错误消息,指出message未定义变量(又称未声明变量),当然,Typescript编译器不应允许您这样做,但实际上没有什么可以阻止您。

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

编译器很乐意仅编译上面的代码。因此,如果您确定所有变量都已声明,则只需执行此操作

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

上面的代码将检查nullundefined,但是在message未声明变量的情况下(出于安全考虑),您可以考虑以下代码

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

注意:这里的顺序typeof(message) !== 'undefined' && message !== null非常重要,您必须先检查undefined状态,否则将与message != null@Jaider一样。


4
M. Kamal如果某物= 0,则用!something进行验证会给您带来麻烦。
justcode '18

1
@arturios您能给我一个例子吗!
艾哈迈德·卡马尔

2
@arturios但是0在JavaScript中已经是虚假的值了!那么这有什么意义呢?
艾哈迈德·卡马尔

1
@ Al-un nope,在这里
Ahmed Kamal

1
更新的版本是错误的。检查的第一件事应该是未定义的...,例如:if(typeof something !== 'undefined' && something !== null){...}
Jaider

27

TypeScript 3.7中,我们现在有了Optional chainingNullish Coalescing来同时检查nullundefined,例如:

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

此代码将检查是否已定义foo,否则将返回undefined

旧方法

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

这个:

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

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

使用可选的链接将是:

let x = foo?.bar();

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

另一个新功能是Nullish Coalescing,例如:

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

旧方法:

let x = (foo !== null && foo !== undefined) ?
foo :
bar();

3
这应该是现在公认的答案。Typescript 3.7还支持“空位合并”。var foo = PossibleUndefinedOrNull?fallbackValueIfFirstValueIsUndefinedOrNull; 下面是文档:typescriptlang.org/docs/handbook/release-notes/...
tkd_aj

23

您可能要尝试

if(!!someValue)

!!

说明

第一个!将您的表达变成一个boolean价值。

然后!someValuetrue如果someValue虚假的false如果someValue真实的。这可能会造成混淆。

通过添加另一个!,表达现在true如果someValuetruthy并且false如果someValuefalsy,这是更容易管理。

讨论区

现在,if (!!someValue)当类似的东西if (someValue)会给我同样的结果时,为什么还要打扰我呢?

因为!!someValue正是布尔表达式,而someValue绝对可以是任何东西。这种表达现在可以编写函数(上帝需要这些),例如:

isSomeValueDefined(): boolean {
  return !!someValue
}

代替:

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

希望对您有所帮助。


因此,如果someValue为'false'(具有字符串类型),那么!! someValue为false(布尔类型)?
保罗

我想你可能会这么说。这项技术正是用来避免这种混乱的。我希望你喜欢它!
avi.elkharrat

但是令我困惑的是!!'false'等于true。仅仅因为这种情况,我不能使用这种技术。
保罗

!!'false'的行为,true因为'false'是有效的字符串
avi.elkharrat

因此,该技术无法解决此问题,或者是否有解决方法?
保罗

16

因为Typescript 2.x.x您应该按照以下方式进行操作(使用类型guard):

tl; dr

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

为什么?

这样,isDefined()将尊重变量的类型,下面的代码将考虑此检查。

示例1-基本检查:

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

示例2-类型方面:

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

14
if(data){}

意思是!数据

  • 空值
  • 未定义
  • ....

2
如果数据是布尔类型?
ianstigator

你可以结合两个变量,例如。if(value1 && value2)检查它们是否都未定义?
ARK

@ianstigator布尔值可以等于truefalse仅被评估。如果您的布尔值带有赋值nullundefined值,则在两种情况下,该值都将被评估为false
KBeDev

5

如果使用TypeScript,则是让编译器检查null和undefined(或其可能性)的一种更好的方法,而不是在运行时检查它们。(如果您确实想在运行时进行检查,那么只要有很多答案表明,请使用value == null)。

使用compile选项strictNullChecks告诉编译器阻塞可能为null或未定义的值。如果设置此选项,并且在某些情况下确实希望允许null和undefined,则可以将类型定义为Type | null | undefined


5

如果你想通过tslint不设置strict-boolean-expressionsallow-null-union或者allow-undefined-union,你需要使用isNullOrUndefinednodeutil模块或滚你自己:

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

不完全是语法糖,但在您的tslint规则严格时很有用。


1

更快更短的null支票表示法可以是:

value == null ? "UNDEFINED" : value

该行等效于:

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

特别是当您有很多null支票时,这是一个很好的简短表示法。


1

我遇到了这个问题,某些答案工作正常,JSTS原因并非如此。

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

很好,因为JS没有类型

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

在TS如果变量不是用定义null当您尝试以检查nulltslint| 编译器会抱怨。

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

1

加入该线程的时间较晚,但是我发现此JavaScript hack非常方便检查值是否未定义

 if(typeof(something) === 'undefined'){
   // Yes this is undefined
 }

1

通常我会像Fenton所讨论的那样进行杂耍检查。为了使其更具可读性,您可以使用ramda中的isNil。

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

totalAmount = isNil(totalAmount ) ? 0 : totalAmount ;

1

作为一个详细的方法,如果你想比较不确定ONLY,使用下面的示例代码,以供参考:

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

如果incomingValue未声明,则TypeScript应该返回异常。如果已声明但未定义,console.log()则将返回“传入值是:未定义”。请注意,我们没有使用严格等于运算符。

“正确”的方式(请查看其他答案以获取详细信息),如果incomingValuea不是boolean类型,则仅评估其值是否为true,这将根据常量/变量类型进行评估。一个true字符串必须使用被明确定义为字符串= ''分配。如果不是,它将被评估为false。让我们使用相同的上下文检查这种情况:

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

somethingToCompare ==(未定义|| null)。(未定义|| null)解析为null,因此这是somethingToCompare和null之间的松散比较
carlosvini

@carlosvini当然,比较的重点是冗长并提供参考代码。这就是非严格相等比较的原因。答案的目的是清楚明确。我将编辑文本以避免混淆
KBeDev


0

所有,

如果您使用的是对象,那么投票数最多的答案实际上并不会起作用。在这种情况下,如果不存在属性,则检查将无法进行。这就是我们的问题:请参见以下示例:

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

结果:

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

plunkr链接:https ://plnkr.co/edit/BJpVHD95FhKlpHp1skUE


这不是很好的测试。这些值都不严格 null。试试这个:plnkr.co/edit/NfiVnQNes1p8PvXd1fCG?p=preview
simonhamp

0

由于TypeScript是ES6 JavaScript的类型化超集。lodash是一个javascript库。

使用lodash可以检查值是否为null或未定义_.isNil()

_.isNil(value)

争论

(*):要检查的值。

退货

(布尔):如果值是nullish,否则为假,则返回true。

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

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

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

链接

Lodash文件


1
为什么此方法为-2?Lodash对类型脚本不好吗?
Thomas Poignant

0

请注意,如果您使用的是本地存储,则可以使用字符串undefined而不是值undefined结束:

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

人们可能会发现这很有用: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);
  });
});

-4

我总是这样写:

var foo:string;

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

这可以正常工作,并且我认为它可读性强。


21
不能用于数字,因为0也通过了!foo测试。
哈森

10
undefined也不同于的布尔值也不起作用false。这在可选的布尔函数参数中非常普遍,您应使用通用的JavaScript方法:function fn(flag?: boolean) { if (typeof flag === "undefined") flag = true; /* set default value */ }
Gingi

对于booleans似乎可以正常工作var isTrue; if(isTrue)//skips, if(!isTrue)// enters if(isTrue === undefined)//enters。还在var isTrue:boolean未定义的打字稿中尝试过,如果检查则同样。@Gingi,您尝试过的内容和我尝试过的内容是否有所不同?
德雷奈
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.