Apakah ada cara untuk memeriksa `null` dan` undefined`?


382

Karena TypeScript sangat diketik, cukup gunakan if () {}untuk memeriksa nulldan undefinedtidak terdengar benar.

Apakah TypeScript memiliki fungsi khusus atau sintaksis gula untuk ini?


9
Since TypeScript is strongly-typedSaya tidak dapat menemukan ini di dokumen itu dan saya ragu tentang hal itu ...
pawciobiel

3
Rekomendasikan untuk membaca pada jenis terbaru yang tidak dapat dibatalkan, ini adalah ScriptScript 2, tetapi sudah dalam versi beta hari ini. [Jenis yang tidak dapat dibatalkan # 7140] ( github.com/Microsoft/TypeScript/pull/7140 )
RyBolt

2
TypeScript tidak memiliki fungsi khusus untuk melakukan apa pun. Ini adalah sistem pengetikan dan transpiler, bukan perpustakaan.

Jawaban:


378

Menggunakan cek-juggling, Anda dapat menguji keduanya nulldan undefineddalam satu pukulan:

if (x == null) {

Jika Anda menggunakan pemeriksaan ketat, itu hanya akan benar untuk nilai yang disetel ke nulldan tidak akan dievaluasi sebagai benar untuk variabel yang tidak ditentukan:

if (x === null) {

Anda dapat mencoba ini dengan berbagai nilai menggunakan contoh ini:

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

Keluaran

"a == null"

"a tidak terdefinisi"

"b == null"

"b === null"


52
Apa itu "juggling-check"?
kolobok

18
@akapelko di sinilah jenisnya disulap (yaitu "bisakah kita membuat tipe ini menjadi boolean"). Jadi string kosong diperlakukan sebagai boolean false, misalnya. Bug yang umum ketika juggling adalah: "false" == falsestring yang tidak kosong seperti "false" dievaluasi true.
Fenton

12
Ini karena 'type coersion' JS.
Astravagrant

Kecuali jika x adalah 0 (dan itu adalah nilai yang valid), itu akan lulus uji undefined / null Anda.
Jon Gunter

3
@JonGunter yang akan berlaku untuk if(x)pemeriksaan gaya truthy / falsey , tetapi tidak if(x == null), yang hanya menangkap nulldan undefined. Periksa menggunakannya var c: number = 0; check(c, 'b');bukan "sepenuhnya" null,, atau undefined.
Fenton

269
if( value ) {
}

akan mengevaluasi truejika valuetidak:

  • null
  • undefined
  • NaN
  • string kosong ''
  • 0
  • false

naskah termasuk aturan javascript.


12
Bagaimana jika nilainya dari tipe boolean?
ianstigator

Anda dapat menggabungkan dua variabel misalnya. if (value1 && value2) untuk memeriksa apakah keduanya tidak terdefinisi?
BAHKAN

8
@ RamazanSağır ya terima kasih saya tahu itu, tetapi kenyataannya adalah 0 nilai adalah sesuatu yang valid yang dapat saya miliki, satu-satunya pemeriksaan yang ingin saya lakukan adalah variabelnya tidak nol atau tidak terdefinisi. Saya telah membaca bahwa saya dapat melakukannya dengan menggunakan val! = Null (the! = Bukannya! == juga memeriksa nilai yang tidak ditentukan)
Alex

4
Solusi ini tidak akan berfungsi jika aturan tslint - "strict-boolean-expressions" diaktifkan.
ip_x

1
Ini akan mengevaluasi false jika menilai kita falsy, sesederhana ini.
Ayfri

50

Apakah TypeScript memiliki fungsi khusus atau gula sintaks untuk ini

TypeScript sepenuhnya memahami versi JavaScript yang ada something == null.

TypeScript akan dengan benar mengesampingkan keduanya nulldan undefineddengan pemeriksaan seperti itu.

Lebih

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


1
Saya suka melakukan dua hal yang sama myVar == null. Hanya pilihan lain.
David Sherret

30
== nulladalah cara yang benar untuk menguji null & tidak terdefinisi. !!somethingadalah paksaan yang tidak berguna dalam kondisi di JS (hanya digunakan something). !!somethingakan juga memaksa 0 dan '' ke false, yang bukan apa yang ingin Anda lakukan jika Anda mencari null / undefined.
C Snover

39

Saya melakukan berbagai tes di taman bermain naskah:

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

memberi:

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

begitu:

  • memeriksa apakah (a == null) benar untuk mengetahui apakah a adalah nol atau tidak terdefinisi
  • memeriksa apakah (a! = null) benar untuk mengetahui apakah a didefinisikan
  • memeriksa apakah (a) salah untuk mengetahui apakah a didefinisikan

1
Mengapa Anda menggunakan taman bermain TypeScript untuk ini? Tidak ada yang berhubungan dengan TypeScript di sini.

10
Karena pertanyaannya terkait dengan Typcript, saya mencoba menguji berbagai solusi yang diajukan terhadap transpiler Typcript.
Juangui Jordán

6
TS transpiler tidak akan mengubah kode ini sama sekali.

31

Saya pikir jawaban ini membutuhkan pembaruan, periksa riwayat edit untuk jawaban yang lama.

Pada dasarnya, Anda memiliki tiga kasus berbeda nol, tidak terdefinisi, dan tidak diumumkan, lihat cuplikan di bawah ini.

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

Anda akan mendapatkan kesalahan yang mengatakan bahwa variabel messagetidak terdefinisi (alias tidak dideklarasikan), tentu saja, kompiler Script tidak boleh membiarkan Anda melakukan itu tetapi BENAR-BENAR tidak ada yang dapat mencegah Anda.

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

Compiler akan dengan senang hati mengkompilasi kode di atas. Jadi, jika Anda yakin bahwa semua variabel dideklarasikan, Anda bisa melakukannya

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

kode di atas akan memeriksa nulldan undefined, TETAPI jika messagevariabelnya mungkin tidak dideklarasikan (untuk keamanan), Anda dapat mempertimbangkan kode berikut

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

Catatan: pesanan di sini typeof(message) !== 'undefined' && message !== nullsangat penting, Anda harus memeriksa undefinedkeadaan terlebih dahulu, sama saja dengan message != null, terima kasih @Jaider.


4
M. Kamal jika sesuatu = 0, verifikasi Anda dengan! Sesuatu akan memberi Anda masalah.
justcode

1
@arturios, tolong beri saya contoh !!
Ahmed Kamal

2
@arturios Tapi 0 sudah menjadi nilai palsu dalam JavaScript !! jadi apa gunanya di sini?
Ahmed Kamal

1
@ Al-un nggak, lihat sedang beraksi di sini
Ahmed Kamal

1
versi yang diperbarui salah. Hal pertama yang harus diperiksa harus tidak ditentukan ... seperti:if(typeof something !== 'undefined' && something !== null){...}
Jaider

27

Dalam TypeScript 3.7 sekarang kita memiliki rantai opsional dan Nullish Penggabungan untuk memeriksa nol dan undefined dalam waktu yang sama, contoh:

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

kode ini akan memeriksa apakah foo didefinisikan sebaliknya akan kembali tidak terdefinisi

cara lama :

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

ini:

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

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

Dengan rantai opsional akan:

let x = foo?.bar();

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

fitur baru lainnya adalah Nullish Coalescing , contoh:

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

cara lama:

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

3
Ini harus menjadi jawaban yang diterima sekarang. Typescript 3.7 juga mendukung "Nullish Coalescing". var foo = mungkinUndefinedOrNull ?? fallbackValueIfFirstValueIsUndefinedOrNull; Berikut dokumentasinya: typescriptlang.org/docs/handbook/release-notes/…
tkd_aj

23

Anda mungkin ingin mencoba

if(!!someValue)

dengan !!.

Penjelasan

Yang pertama !akan mengubah ekspresi Anda menjadi sebuah booleannilai.

Kemudian !someValueadalah truejika someValueadalah falsy dan falsejika someValueadalah truthy . Ini mungkin membingungkan.

Dengan menambahkan lain !, ekspresi sekarang truejika someValueini truthy dan falsejika someValueadalah falsy , yang jauh lebih mudah untuk mengelola.

Diskusi

Sekarang, mengapa saya repot-repot if (!!someValue)ketika sesuatu seperti if (someValue)akan memberi saya hasil yang sama?

Karena !!someValuejustru ungkapan boolean, padahal someValuebisa jadi apa saja. Ekspresi semacam ini sekarang akan memungkinkan untuk menulis fungsi (dan Tuhan membutuhkan kita) seperti:

isSomeValueDefined(): boolean {
  return !!someValue
}

dari pada:

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

Saya harap ini membantu.


jadi, jika someValue adalah 'false' (dengan tipe string), maka !! someValue is false (tipe boolean)?
paul cheung

Saya kira Anda dapat mengatakan demikian. Teknik ini tepat digunakan untuk menghindari kebingungan seperti ini. Saya harap Anda menyukainya!
avi.elkharrat

tetapi yang membingungkan saya adalah 'salah' sama dengan benar. Hanya karena kasus ini, saya tidak dapat menggunakan teknik ini.
paul cheung

!!'false' memang true karena 'false'merupakan string yang valid
avi.elkharrat

jadi teknik ini tidak bisa menutupi kasus ini, atau adakah solusi penyelesaiannya?
paul cheung

16

Untuk itu Typescript 2.x.xAnda harus melakukannya dengan cara berikut (menggunakan tipe guard ):

tl; dr

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

Mengapa?

Dengan cara ini isDefined()akan menghormati jenis variabel dan kode berikut akan tahu ambil akun cek ini.

Contoh 1 - cek dasar:

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

Contoh 2 - jenis hormat:

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

itu berarti! data

  • batal
  • tidak terdefinisi
  • Salah
  • ....

2
Dan jika data bertipe boolean?
ianstigator

Anda dapat menggabungkan dua variabel misalnya. if (value1 && value2) untuk memeriksa apakah keduanya tidak terdefinisi?
BAHKAN

@ianstigator Boolean dapat dievaluasi sebagai trueatau falsehanya. Jika Anda memiliki boolean dengan nullpenugasan atau undefinednilai, dalam kedua kasus nilai akan dievaluasi sebagai false.
KBeDev

5

Jika Anda menggunakan TypeScript, itu adalah pendekatan yang lebih baik untuk membiarkan kompiler memeriksa nol dan tidak terdefinisi (atau kemungkinan daripadanya), daripada memeriksanya pada saat run-time. (Jika Anda ingin memeriksa pada saat run-time, maka seperti yang ditunjukkan oleh banyak jawaban, gunakan saja value == null).

Gunakan opsi kompilasi strictNullChecksuntuk memberi tahu kompiler untuk mencekik kemungkinan nilai nol atau tidak terdefinisi. Jika Anda menetapkan pilihan ini, dan kemudian ada situasi di mana Anda tidak ingin mengizinkan nol dan terdefinisi, Anda dapat menentukan jenis sebagai Type | null | undefined.


5

Jika Anda ingin lulus tslinttanpa pengaturan strict-boolean-expressionsuntuk allow-null-unionatau allow-undefined-union, Anda perlu menggunakan isNullOrUndefineddari node's utilmodul atau roll Anda sendiri:

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

Bukan gula sintaksis tetapi berguna ketika aturan tslint Anda ketat.


1

Notasi yang lebih cepat dan lebih pendek untuk nullcek dapat:

value == null ? "UNDEFINED" : value

Baris ini setara dengan:

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

Terutama ketika Anda memiliki banyak nullcek itu adalah notasi pendek yang bagus.


1

Saya punya masalah ini dan beberapa jawaban berfungsi dengan baik untuk JStetapi tidak untuk di TSsini adalah alasannya.

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

Itu semua baik karena JS tidak memiliki Jenis

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

Dalam TS jika variabel tidak didefinisikan dengan nullketika Anda mencoba untuk memeriksa bahwa nullitu tslint| kompiler akan mengeluh.

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

Terlambat untuk bergabung dengan utas ini, tetapi saya menemukan peretasan JavaScript ini sangat berguna dalam memeriksa apakah suatu nilai tidak ditentukan

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

1

Biasanya saya melakukan pemeriksaan juggling seperti yang sudah dibahas Fenton . Untuk membuatnya lebih mudah dibaca, Anda dapat menggunakan isNil dari ramda.

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

totalAmount = isNil(totalAmount ) ? 0 : totalAmount ;

1

Sebagai cara verbose, jika Anda ingin membandingkan nilai-nilai null dan undefined ONLY , gunakan contoh kode berikut untuk referensi:

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

Jika incomingValuetidak dideklarasikan, TypeScript harus mengembalikan pengecualian. Jika ini dinyatakan tetapi tidak didefinisikan, theconsole.log() akan mengembalikan "Nilai masuk adalah: tidak terdefinisi". Catatan kami tidak menggunakan operator sama dengan ketat.

Cara "benar" (periksa jawaban lain untuk detail), jika incomingValuebukan booleantipe, cukup evaluasi jika nilainya benar, ini akan dievaluasi sesuai dengan tipe konstan / variabel. Sebuah truestring harus didefinisikan secara eksplisit sebagai string menggunakan = ''penugasan. Jika tidak, itu akan dievaluasi sebagai false. Mari kita periksa kasus ini menggunakan konteks yang sama:

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 == (undefined || null). (undefined || null) memutuskan untuk nol, jadi ini adalah perbandingan longgar antara somethingToCompare dan null
carlosvini

@carlosvini Tentu, titik perbandingannya adalah verbose dan memberikan kode untuk referensi. Itulah alasan perbandingan yang tidak ketat sama. Tujuan jawabannya adalah jelas dan eksploratif. Saya akan mengedit teks untuk menghindari kebingungan
KBeDev


0

Semua,

Jawaban dengan suara terbanyak, tidak benar-benar berfungsi jika Anda bekerja dengan suatu objek. Dalam hal itu, jika sebuah properti tidak ada, cek tidak akan berfungsi. Dan itu adalah masalah dalam kasus kami: lihat contoh ini:

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

Hasil:

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

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


Ini bukan ujian yang bagus. Tidak satu pun dari nilai-nilai itu yang ketat null . Coba ini: plnkr.co/edit/NfiVnQNes1p8PvXd1fCG?p=preview
simonhamp

0

Karena TypeScript adalah superset yang diketik dari JavaScript ES6. Dan lodash adalah perpustakaan javascript.

Menggunakan lodash untuk memeriksa apakah nilai nol atau tidak dapat ditentukan dapat dilakukan dengan menggunakan _.isNil().

_.isNil(value)

Argumen

nilai (*): Nilai yang akan diperiksa.

Kembali

(boolean) : Mengembalikan nilai true jika nilai nullish, atau false.

Contoh

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

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

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

Tautan

Lodash Documents


1
Mengapa metode ini -2? Lodash tidak pandai dengan skrip jenis?
Thomas Poignant

0

Hati-hati jika Anda menggunakan penyimpanan lokal, Anda bisa berakhir dengan string tidak terdefinisi daripada nilai tidak terdefinisi:

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

Orang-orang mungkin menemukan ini berguna: 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

Saya selalu menulis seperti ini:

var foo:string;

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

Ini akan berfungsi dengan baik dan saya pikir itu sangat mudah dibaca.


21
Tidak akan berfungsi untuk angka karena 0juga lulus !footes.
Hasen

10
Tidak bekerja untuk boolean juga, di mana undefinedberbeda false. Ini sangat umum dengan parameter fungsi boolean opsional, di mana Anda harus menggunakan pendekatan JavaScript yang umum:function fn(flag?: boolean) { if (typeof flag === "undefined") flag = true; /* set default value */ }
Gingi

Tampaknya ok bekerja untuk boolean: var isTrue; if(isTrue)//skips, if(!isTrue)// enters if(isTrue === undefined)//enters. Juga mencobanya dalam naskah dengan var isTrue:booleanyang tidak terdefinisi, dan sama jika diperiksa. @Gingi, apakah ada sesuatu yang berbeda tentang apa yang Anda coba dan apa yang saya coba?
Drenai
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.