Чи є спосіб перевірити і "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.