Есть ли способ проверить как `null`, так и` undefined`?

382

Поскольку TypeScript строго типизирован, просто используется 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) {

Если вы используете строгий контроль, он будет иметь значение true только для значений, установленных nullи не будет оцениваться как 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 == ноль"

"b === ноль"

Фентон
источник
52
Что такое «жонглирование»?
Колобок
18
@akapelko - это место, где тип является жонглированным (т. е. «мы можем сделать этот тип логическим») Так, например, пустая строка рассматривается как логическое значение false. Типичная ошибка при жонглировании: "false" == falseнепустая строка, такая как "false", оценивается как true.
Фентон
12
Это связано с «принуждением типов» в JS.
Остравагрант
За исключением случаев, когда x равен 0 (и это допустимое значение), он пройдет ваш неопределенный / нулевой тест.
Джон Гюнтер
3
@JonGunter, это было бы верно для проверок if(x)стиля истина / фальси , но не if(x == null), которые только ловят nullи undefined. Проверьте это, используя var c: number = 0; check(c, 'b');не "nully" null, или undefined.
Фентон
270
if( value ) {
}

оценим, trueесли valueнет:

  • null
  • undefined
  • NaN
  • пустой строкой ''
  • 0
  • false

машинопись включает в себя правила JavaScript.

Рамазан Сагыр
источник
12
Что если значение имеет логический тип?
ianstigator
Можете ли вы объединить две переменные, например. if (value1 && value2), чтобы проверить, являются ли они оба неопределенными?
ARK
8
@ RamazanSağır да, спасибо, я знаю это, но факт в том, что значение 0 - это то, что я могу иметь, единственная проверка, которую я хочу сделать, - это то, что переменная не является ни нулевой, ни неопределенной. Я прочитал, что могу сделать это, используя val! = Null (! = Вместо! == также проверяет неопределенное значение)
Alex
4
Это решение не будет работать, если включено правило tslint - "strict-boolean-expressions".
ip_x
1
Он оценит ложь, если оцените нас как ложь, так просто.
Айфри
50

Есть ли в TypeScript выделенная функция или синтаксический сахар для этого

TypeScript полностью понимает версию JavaScript, которая есть something == null.

TypeScript будет правильно исключать как nullи undefinedс такими проверками.

Больше

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

basarat
источник
1
Мне нравится делать два равных myVar == null. Просто еще один вариант.
Дэвид Шеррет
30
== nullправильный способ проверки на ноль и неопределенность. !!somethingбесполезное принуждение в условном выражении в JS (просто используйте something). !!somethingтакже приведёт 0 и '' к ложному, что не то, что вы хотите сделать, если вы ищете 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), чтобы узнать, является ли значение null или неопределенным
  • проверка правильности (a! = null), чтобы узнать, определен ли a
  • проверка, если (а) неверно, чтобы узнать, определен ли
Хуанги Джордан
источник
1
Зачем вам использовать площадку TypeScript для этого? Ничто здесь не имеет ничего общего с TypeScript.
10
Поскольку вопрос был связан с Typescript, я пытался протестировать различные предлагаемые решения с помощью транспилятора Typescript.
Хуангуи Джордан
6
Транспортер TS вообще не будет преобразовывать этот код.
31

Я думаю, что этот ответ нуждается в обновлении, проверьте историю изменений для старого ответа.

По сути, у вас есть три разных случая: null, undefined и undeclared, см. Фрагмент ниже.

// 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-ун Неа, увидеть его в действии здесь
Ахмед Камал
1
обновленная версия неверна. Первое, что нужно проверить, должно быть неопределенным ... как:if(typeof something !== 'undefined' && something !== null){...}
Jaider
27

В TypeScript 3.7 у нас теперь есть Optional Chaining и Nullish Coalescing, чтобы проверять null и undefined одновременно, например:

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 также поддерживает «Nullish Coalescing». var foo = возможныхUndefinedOrNull ?? fallbackValueIfFirstValueIsUndefinedOrNull; Вот документация: typescriptlang.org/docs/handbook/release-notes/…
tkd_aj
23

Вы можете попробовать

if(!!someValue)

с !!.

объяснение

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

Тогда !someValue, trueесли someValueэто ложь, и falseесли someValueэто правда . Это может сбивать с толку.

При добавлении другого !, выражение теперь , trueесли someValueэто truthy и falseесли someValueэто falsy , что намного легче управлять.

обсуждение

Теперь, почему я беспокоюсь, if (!!someValue)когда что-то подобное if (someValue)дало бы мне тот же результат?

Потому что !!someValueэто как раз логическое выражение, тогда как someValueможет быть абсолютно любым. Этот вид выражения теперь будет позволять писать функции (и Бог нам это нужен), такие как:

isSomeValueDefined(): boolean {
  return !!someValue
}

вместо:

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

Я надеюсь, что это помогает.

avi.elkharrat
источник
Итак, если someValue равно 'false' (со строковым типом), то !! someValue равно false (логический тип)?
Пол Чунг
Я думаю, вы можете так сказать. Эта техника точно используется, чтобы избежать такого рода путаницы. Я надеюсь тебе это понравится!
avi.elkharrat
но то, что смутило меня, - это «ложь» - это правда Только из-за этого случая я не могу использовать эту технику.
Пол Чунг
!!'false'на деле, trueпотому что 'false'это допустимая строка
avi.elkharrat
так что эта техника не может охватить этот случай, или есть обходное решение?
Пол Чунг
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){}

это значит! данные

  • значение NULL
  • не определено
  • ложный
  • ....
artemitSoft
источник
2
А если данные булева типа?
ianstigator
Можете ли вы объединить две переменные, например. if (value1 && value2), чтобы проверить, являются ли они оба неопределенными?
АРК
@ianstigator Логическое значение может быть оценено как trueили falseтолько. Если у вас есть логическое значение с nullприсваиванием или undefinedзначением, в обоих случаях значение будет оцениваться как false.
KBeDev
5

Если вы используете TypeScript, лучше подходить к компилятору, чтобы он проверял наличие нулей и неопределенных значений (или возможность этого), а не проверял их во время выполнения. (Если вы хотите проверить во время выполнения, то, как указывают многие ответы, просто используйте value == null).

Используйте опцию compile, 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);
}

В ТС , если переменная не была определена с , 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'.
T04435
источник
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()будет возвращено «Входящее значение: undefined». Обратите внимание, что мы не используем оператор строгого равенства.

«Правильный» способ (проверьте другие ответы для деталей), если 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"
}
KBeDev
источник
SomeToCompare == (undefined || null). (undefined || null) преобразуется в null, так что это
бесполезное
@carlosvini Конечно, смысл сравнения - быть многословным и предоставить код для справки. Вот причина нестрогого сравнения равных. Цель ответа - быть ясным и объяснительным. Я буду редактировать текст, чтобы избежать путаницы
KBeDev,
0

ты можешь использовать

if(x === undefined)
Акшай Редди
источник
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)

аргументы

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

Возвращает

(логическое значение) : возвращает значение true, если значение равно нулю, иначе значение false.

пример

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

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

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

Ссылка на сайт

Lodash Docs

7e2e63de
источник
1
Почему этот метод -2? Лодаш не хорошо с типом сценария?
Томас Пойнант
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";    
}

Это будет хорошо работать, и я думаю, что это очень читабельно.

AlexB
источник
21
Не будет работать для чисел, потому что 0также проходит !fooтест.
Хазен
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которой был неопределен, и то же самое, если проверяет. @ Джинги, есть что-то другое в том, что ты пробовал и что я пробовал?
Дренаи