Чи є спосіб перевірити і "null", і "undefined"?


381

Так машинопис сильно типізованих, просто використовуючи if () {}для перевірки nullі undefinedне звучить.

Чи має TypeScript для цього якусь виділену функцію або синтаксичний цукор?


9
Since TypeScript is strongly-typedЯ не міг знайти це у своїх документах, і я маю сумніви з цього приводу ...
— pawciobiel

3
Рекомендую ознайомитись з останніми ненульовими типами, це Typescript 2, але вже на сьогоднішній день у бета-версії. [Ненульові типи № 7140] ( github.com/Microsoft/TypeScript/pull/7140 )
— RyBolt

2
У TypeScript немає виділених функцій, щоб щось робити. Це система друку і транспілятор, а не бібліотека.

Відповіді:


378

Використовуючи перевірку жонглювання, ви можете протестувати як nullі undefinedодним ударом:

if (x == null) {

Якщо ви використовуєте строгу перевірку, вона буде істинною лише для встановлених значень nullі не буде оцінюватися як істинна для невизначених змінних:

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

Вихідні дані

"a == null"

"a не визначено"

"b == null"

"b === null"


52
Що таке "жонглювання"?
— колобок

18
@akapelko - це там, де тип переміщується (тобто "чи можемо ми зробити цей тип булевим"). Так, наприклад, порожня рядок трактується як булева помилка. Поширена помилка при жонглюванні: "false" == falseне порожня рядок типу "false" оцінюється до true.
— Фентон,

12
Це пояснюється типовим примусом JS.
— Астравагрант

За винятком випадків, коли x дорівнює 0 (і це дійсне значення), він пройде ваш невизначений / нульовий тест.
— Джон Гунтер

3
@JonGunter, що було би правдою для перевірок if(x)стилю truthy / falsey , але ні if(x == null), що тільки ловить nullі undefined. Перевірте, використовуючи var c: number = 0; check(c, 'b');його не "нульовим" null, або undefined.
— Фентон

268
if( value ) {
}

оцінюємо, trueякщо valueні:

  • null
  • undefined
  • NaN
  • порожній рядок ''
  • 0
  • false

машинопис включає правила javascript.


12
Що робити, якщо значення булевого типу?
— ianstigator

чи можете ви поєднати дві змінні, наприклад. якщо (value1 && value2), щоб перевірити, чи обидва вони не визначені?
— ARK

8
@ RamazanSağır, дякую, я знаю, але факт 0 значення є чимось дійсним, що я можу мати. Єдина перевірка, яку я хочу зробити, це те, що змінна не є ні нульовою, ні визначеною. Я читав, що я можу це зробити, використовуючи val! = Null (the! = Замість! == також перевіряє невизначене значення)
— Alex

4
Це рішення не працюватиме, якщо включено правило tslint - "строгі булеві вирази".
— ip_x

1
Він буде оцінювати помилкове значення, якщо ми цінуємо помилкове, настільки ж просто.
— Айфрі

50

Чи має TypeScript для цього виділений функцію або синтаксичний цукор

TypeScript повністю розуміє версію JavaScript, яка є something == null .

TypeScript правильно виключає і nullта, іundefined такі перевірки.

Більше

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


1
Мені подобається робити дві рівні myVar == null. Просто ще один варіант.
— Девід Шеррет

30
== nullце правильний спосіб тестування на null & undefined. !!somethingє марною примусовою умовою в JS (просто використання something). !!somethingбуде також примушувати 0 та "" до false, що не є тим, що ви хочете робити, якщо шукаєте null / undefined.
— C Snover

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 чи undefined
  • перевірка правильності (a! = null), щоб знати, чи визначено a
  • перевірка, якщо (а) неправильно знати, чи визначено a

1
Навіщо використовувати для цього майданчик TypeScript? Ніщо тут не має нічого спільного з TypeScript.

10
Оскільки питання стосувалося Typescript, я намагався перевірити різні запропоновані рішення проти транспілятора Typescript.
— Хуангуй Йордан

6
Транспілятор TS взагалі не перетворював би жодного з цих кодів.

31

Я думаю, що ця відповідь потребує оновлення, перевірте історію редагування на стару відповідь.

В основному, у вас є три випадкові випадки: нульові, невизначені та незадекларовані, див. Фрагмент нижче.

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

Ви отримаєте помилку, говорить про те, що змінна messageне визначена (вона також недекларована), звичайно, компілятор Typescript не повинен дозволяти вам це робити, але НАДАЛЬНО нічого не може вам завадити.

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

Компілятор буде радий просто скласти код вище. Отже, якщо ви впевнені, що всі змінні оголошені, ви можете просто зробити це

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

Наведений вище код перевірятиме nullі undefined, АЛЕ в разі 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
М. Камал, якщо щось = 0, ваша перевірка з! Щось доставить вам проблеми.
— простокод

1
@arturios, будь ласка, приведіть мені приклад !!
— Ахмед Камал

2
@arturios Але 0 - це вже хибне значення в JavaScript !! так що тут сенс?
— Ахмед Камал

1
@ Al-un nope, дивіться це в дії тут
— Ахмед Камал

1
оновлена ​​версія помилкова. Перше, що потрібно перевірити, має бути невизначеним ... на кшталт:if(typeof something !== 'undefined' && something !== null){...}
— Jaider

27

Зараз у TypeScript 3.7 у нас є необов'язкове ланцюжок і Nullish Coalescing, щоб перевірити нульові та невизначені одночасно, наприклад:

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

цей код перевірить, чи визначено foo, інакше він повернеться невизначеним

старий спосіб :

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 також підтримує "Nullish Coalescing". var foo = можливийUndefinedOrNull ?? backbackValueIfFirstValueIsUndefinedOrNull; Ось документація: typescriptlang.org/docs/handbook/release-notes / ...
— tkd_aj

23

Ви можете спробувати

if(!!someValue)

з !!.

Пояснення

Перший !перетворить ваше вираження в аboolean значення.

Тоді !someValueяк , trueякщо someValueце falsy і falseякщо someValueце truthy . Це може заплутати.

Додавши ще одне !, вираз тепер є, trueякщо someValueє неправдоподібним, а falseякщо someValue- хибним , що керувати набагато простіше.

Обговорення

Тепер, чому я морочу себе, if (!!someValue)коли щось подібнеif (someValue) дало б мені такий же результат?

Тому що !!someValueсаме булевий вираз, тоді як someValueможе бути абсолютно все. Цей вираз тепер дозволить записати функції (а Бог нам це потрібен), наприклад:

isSomeValueDefined(): boolean {
  return !!someValue
}

замість:

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

Я сподіваюся, що це допомагає.


Отже, якщо someValue 'false' (з рядковим типом), то !! someValue є хибним (булівський тип)?
— paul cheung

Я думаю, ви можете так сказати. Ця техніка точно використовується, щоб уникнути подібної плутанини. Сподіваюся що вам це подобається!
— avi.elkharrat

але те, що мене збентежило, є !! "хибним" дорівнює правді. Просто через цей випадок я не можу використовувати цю техніку.
— paul cheung

!!'false'є у справі, trueтому що 'false'це дійсна рядок
— avi.elkharrat

тож ця техніка не може висвітлити цю справу, чи існує рішення щодо вирішення проблеми?
— paul cheung

16

Для цього Typescript 2.x.xслід це зробити наступним чином (використовуючи типові гвардії ):

тл; д-р

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

чи можете ви поєднати дві змінні, наприклад. якщо (value1 && value2), щоб перевірити, чи обидва вони не визначені?
— ARK

@ianstigator Булева може бути оцінена як trueабоfalse тільки. Якщо у вас є булева з nullприсвоєнням або undefinedзначенням, в обох випадках значення буде оцінено як false.
— KBeDev

5

Якщо ви використовуєте TypeScript, то краще підходити дозволити компілятору перевірити наявність нулів та невизначених значень (або можливості цього), а не перевіряти їх під час виконання. (Якщо ви хочете перевірити під час виконання, то скільки відповідей вказує, просто використовуйте value == null).

Використовуйте параметр компіляції, strictNullChecksщоб сказати компілятору задушитись можливими нульовими або невизначеними значеннями. Якщо ви встановите цей параметр, а потім виникає ситуація , коли ви дійсно хочете , щоб нуль і невизначеним, ви можете визначити тип , як Type | null | undefined.


5

Якщо ви хочете пройти tslintбез встановлення strict-boolean-expressionsна allow-null-unionабоallow-undefined-union , вам потрібно використовувати isNullOrUndefinedвід node«s utilмодуля або згорнути свій власний:

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

У мене було це питання, і деякі відповіді працюють просто чудово, JSале не для TSцього є причина.

//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коли ви намагаєтеся перевірити, чи nullє tslint| компілятор поскаржиться.

//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 дуже зручним для перевірки, чи значення не визначене

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

1

Зазвичай я роблю перевірку жонглюванням, як уже говорив Фентон . Щоб зробити його більш читабельним, ви можете використовувати isNil від ramda.

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

totalAmount = isNil(totalAmount ) ? 0 : totalAmount ;

1

Як багатослівним чином, якщо ви хочете порівняти нульові і невизначені значення ТІЛЬКИ , використовуйте наступний приклад коду для довідки:

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() то повернеться "Вхідне значення: невизначене". Зверніть увагу, що ми не використовуємо оператор строгої рівності.

"Правильний" спосіб (перевірте інші відповіді на деталі), якщо incomingValueце не booleanтип, просто оцініть, чи є його значенням правдивим, це буде оцінено відповідно до типу "постійний / змінний". 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 == (undefined || null). (undefined || null) вирішує значення null, тому це
— слабке

@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 - це набір суперсети JavaScript ES6. І lodash - це бібліотека javascript.

Використання lodash для перевірки того, що значення є нульовим або невизначеним, можна зробити за допомогою _.isNil().

_.isNil(value)

Аргументи

значення (*): значення для перевірки.

Повертається

(boolean) : Повертає true, якщо значення є нульовим, else false.

Приклад

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

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

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

Посилання

Лодаш Док


1
Чому цей метод дорівнює -2? Лодаш не хороший із типовим сценарієм?
— Thomas Poignant

0

будьте обережні, якщо ви використовуєте локальне сховище, ви можете вказувати рядок не визначений, а не значення 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тест.
— hasen

10
Не працює і для булевих, де undefinedінакше, ніж false. Це дуже часто зустрічається з додатковими булевими параметрами функції, де слід використовувати загальний підхід JavaScript:function fn(flag?: boolean) { if (typeof flag === "undefined") flag = true; /* set default value */ }
— Gingi

Здається , працює нормально для булевих: var isTrue; if(isTrue)//skips, if(!isTrue)// enters if(isTrue === undefined)//enters. Також спробував це в машинописному тексті, з var isTrue:booleanяким не було визначено, і те саме, якщо перевіряється. @Gingi, чи є щось інше в тому, що ти спробував і що я спробував?
— Дренай
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.