V TypeScriptu, co je operátor ! (vykřičník/bang) při dereferencování člena?
Při pohledu na zdrojový kód pravidla tslint jsem narazil na následující výrok:
if (node.parent!.kind === ts.SyntaxKind.ObjectLiteralExpression) {
return;
}
Všimněte si operátoru ! za node.parent. Zajímavé!
Nejprve jsem se pokusil soubor zkompilovat lokálně s mou aktuálně nainstalovanou verzí TS (1.5.3). Výsledná chyba ukázala přesné místo výkřičníku:
tsc --noImplicitAny memberAccessRule.ts
noPublicModifierRule.ts(57,24): error TS1005: ')' expected.
Dále jsem upgradoval na nejnovější TS (2.1.6), který jej zkompiloval bez problémů. Zdá se tedy, že se jedná o vlastnost TS 2.x. Ale transpilace kompletně ignorovala vykřičník, což vedlo k následujícímu JS:
if (node.parent.kind === ts.SyntaxKind.ObjectLiteralExpression) {
return;
}
Má Google fu mě zatím zklamala.
Co je to TS operátor vykřičníku a jak funguje?
Odpověď č. 1
To je operátor ujištění o nenulovosti. Je to způsob, jak říct překladači: ‚tento výraz zde nemůže být null nebo undefined, takže si nestěžuj na možnost, že by mohl být null nebo undefined.‘ Někdy není kontrolor typů schopen učinit toto určení sám.
Je to vysvětleno v poznámkách k vydání TypeScriptu:
Nový postfixový výrazový operátor
!může být použit k zajištění, že jeho operand není null ani undefined v kontextech, kde typový kontrolor není schopen tento fakt určit. Konkrétně, operacex!produkuje hodnotu typuxs vyloučenými hodnotaminullaundefined. Podobně jako typová tvrzení ve formách<T>xax as T, operátor!pro zajištění ne-null je jednoduše odstraněn ve vygenerovaném JavaScript kódu.
Považuji použití termínu „assert“ v tomto vysvětlení za poněkud zavádějící. Je to „assert“ ve smyslu, že to vývojář tvrdí, nikoli ve smyslu, že bude proveden test. Poslední řádek skutečně naznačuje, že nebude generován žádný JavaScriptový kód.
Odpověď č. 2
Louisova odpověď je skvělá, ale myslel jsem, že se ji pokusím stručně shrnout:
Operátor vykřičníku říká kompilátoru, aby dočasně uvolnil omezení „nesmí být null“, které by jinak mohl vyžadovat. Říká kompilátoru: „Jako vývojář vím lépe než ty, že tato proměnná momentálně nemůže být null.“
Odpověď č. 3
Operátor potvrzení nenulovosti
Pomocí operátoru non-null assertion můžeme kompilátoru explicitně sdělit, že výraz má hodnotu jinou než null nebo undefined. To může být užitečné, když kompilátor nemůže s jistotou odvodit typ, ale my máme více informací než kompilátor.
Příklad
Kód TS
function simpleExample(nullableArg: number | undefined | null) {
const normal: number = nullableArg;
// Compile err:
// Type 'number | null | undefined' is not assignable to type 'number'.
// Type 'undefined' is not assignable to type 'number'.(2322)
const operatorApplied: number = nullableArg!;
// compiles fine because we tell compiler that null | undefined are excluded
}
Sestavený JS kód
Všimněte si, že JS nezná pojem operátoru Non-null assertion, protože se jedná o funkci TS.
"use strict";
function simpleExample(nullableArg) {
const normal = nullableArg;
const operatorApplied = nullableArg;
}
Odpověď č. 4
Krátká odpověď
Operátor potvrzení nenulové hodnoty (!) pomáhá překladači, že si jsem jistý, že tato proměnná není null ani undefined.
let obj: { field: SampleType } | null | undefined;
... // some code
// the type of sampleVar is SampleType
let sampleVar = obj!.field; // we tell compiler we are sure obj is not null & not undefined so the type of sampleVar is SampleType
