В TypeScript, что означает оператор ! (восклицательный знак) при разыменовании члена?
При изучении исходного кода правила tslint я наткнулся на следующую строку:
if (node.parent!.kind === ts.SyntaxKind.ObjectLiteralExpression) {
return;
}
Обратите внимание на оператор !
после node.parent
. Интересно!
Сначала я попытался скомпилировать файл локально с установленной у меня версией TypeScript (1.5.3). Полученная ошибка указывала на точное место с восклицательным знаком:
$ tsc --noImplicitAny memberAccessRule.ts
noPublicModifierRule.ts(57,24): error TS1005: ')' expected.
Затем я обновился до последней версии TypeScript (2.1.6), и компиляция прошла без проблем. Таким образом, это, похоже, функция версии TS 2.x. Но транспиляция полностью проигнорировала восклицательный знак, в результате чего получился следующий JavaScript:
if (node.parent.kind === ts.SyntaxKind.ObjectLiteralExpression) {
return;
}
Мои поиски в Google пока не принесли результатов.
Что такое оператор восклицательного знака в TypeScript и как он работает?
5 ответ(ов)
Ответ Луи отличный, но я решил кратко подвести итоги:
Оператор bang (!) говорит компилятору временно ослабить требование "не null", которое он мог бы предъявить. Он сообщает компилятору: "Как разработчик, я знаю лучше, чем ты, что эта переменная сейчас не может быть null".
Оператор утверждения о ненулевом значении
С помощью оператора утверждения о ненулевом значении мы можем явно указать компилятору, что выражение имеет значение, отличное от null
или undefined
. Это может быть полезно в тех случаях, когда компилятор не может точно определить тип, но у нас есть больше информации, чем у компилятора.
Пример
Код на TypeScript
function simpleExample(nullableArg: number | undefined | null) {
const normal: number = nullableArg;
// Ошибка компиляции:
// Тип 'number | null | undefined' не может быть присвоен типу 'number'.
// Тип 'undefined' не может быть присвоен типу 'number'.(2322)
const operatorApplied: number = nullableArg!;
// Компилируется без ошибок, потому что мы говорим компилятору, что null и undefined исключены
}
Скомпилированный JS код
Обратите внимание, что в JS нет концепции оператора утверждения о ненулевом значении, так как это функция TypeScript.
"use strict";
function simpleExample(nullableArg) {
const normal = nullableArg;
const operatorApplied = nullableArg;
}
Таким образом, использование оператора !
позволяет избежать ошибок компиляции, когда вы уверены, что значение переменной не будет равным null
или undefined
.
Краткий ответ
Оператор утверждения о ненулевом значении (!) помогает компилятору понять, что я уверен, что эта переменная не является ни null, ни undefined.
let obj: { field: SampleType } | null | undefined;
... // какой-то код
// тип sampleVar - SampleType
let sampleVar = obj!.field; // мы сообщаем компилятору, что уверены, что obj не null и не undefined, поэтому тип sampleVar - SampleType
Да, вы правы, оператор !
и NonNullable
выполняют схожие задачи, но есть некоторые различия в использовании.
В вашем примере переменная ns
имеет тип string | null
. Когда вы используете оператор !
, вы утверждаете, что ns
не равен null
в момент использования. Таким образом, переменная s1
получает тип string
, потому что вы уверяете TypeScript, что в данный момент ns
содержит строку.
let s1 = ns!;
// ^? let s1: string
С другой стороны, когда вы используете as NonNullable<typeof ns>
, вы фактически преобразуете ns
в тип string
, не давая никакого утверждения о том, что значение не null
на момент выполнения. Это будет работать только в том случае, если ns
действительно не null
, но в отличие от оператора !
, это не изменяет способ проверки типов во время выполнения.
let s2 = ns as NonNullable<typeof ns>;
// ^? let s2: string
Итак, в итоге, если вы уверены, что значение не null
, можете использовать !
, а если хотите применить преобразование типов, не устанавливая такие предубеждения, используйте as NonNullable
. Однако будьте осторожны с использованием !
, так как если значение null
, это приведет к ошибкам во время выполнения.
Не допускающий null (Non-Nullable)
TypeScript выполняет строгие проверки на наличие null, чтобы помочь выявить потенциальные ошибки, связанные с null или undefined. Когда вы пытаетесь получить доступ к члену (свойству или методу) переменной, которая может быть равна null или undefined, TypeScript выдает ошибку компиляции.
let myElement: HTMLElement | null = document.getElementById('myElement');
// Без оператора утверждения о не-null
// Ошибка компиляции: Объект может быть 'null'.
myElement.innerHTML = 'Hello, world!';
// С оператором утверждения о не-null
myElement!.innerHTML = 'Hello, world!';
В приведенном выше примере, если вы не используете оператор утверждения о не-null (!
), TypeScript не позволяет вам получить доступ к свойству innerHTML
, так как myElement
может быть равен null. Однако, используя оператор !
, вы сообщаете компилятору, что уверены, что myElement
не равен null в данный момент, и, следовательно, доступ к свойству innerHTML
может быть выполнен без ошибок. Однако будьте осторожны с использованием оператора !
, так как это может привести к ошибкам выполнения, если переменная на самом деле будет равна null.
Как явно задать новое свойство у `window` в TypeScript?
Как преобразовать строку в число в TypeScript?
Как конвертировать строку в enum в TypeScript?
Как удалить элемент массива в TypeScript?
'unknown' против 'any': в чем разница?