Przeglądając kod źródłowy reguły tslint, natrafiłem na następujące oświadczenie:
if (node.parent!.kind === ts.SyntaxKind.ObjectLiteralExpression) {
return;
}
Zauważ !
operatora po node.parent
. Ciekawy!
Najpierw próbowałem skompilować plik lokalnie z moją aktualnie zainstalowaną wersją TS (1.5.3). Wynikający błąd wskazał dokładną lokalizację huku:
$ tsc --noImplicitAny memberAccessRule.ts
noPublicModifierRule.ts(57,24): error TS1005: ')' expected.
Następnie zaktualizowałem do najnowszej wersji TS (2.1.6), która skompilowała go bez problemu. Wydaje się, że jest to cecha TS 2.x. Ale transpilacja całkowicie zignorowała huk, co spowodowało następujący JS:
if (node.parent.kind === ts.SyntaxKind.ObjectLiteralExpression) {
return;
}
Moje Google fu do tej pory mnie zawiodło.
Co to jest operator wykrzyknika TS i jak działa?
źródło
console.assert()
danej zmiennej przed dodaniem jej!
po niej. Ponieważ add!
mówi kompilatorowi, aby zignorował kontrolę zerową, kompiluje się do noop w javascript. Więc jeśli nie masz pewności, że zmienna ma wartość inną niż null, lepiej wykonaj jawną kontrolę potwierdzenia.dict.has(key) ? dict.get(key) : 'default';
kompilator TS nie może wywnioskować, żeget
wywołanie nigdy nie zwraca wartości null / undefined.dict.has(key) ? dict.get(key)! : 'default';
zawęża typ poprawnie.Odpowiedź Louisa jest świetna, ale pomyślałem, że spróbuję to podsumować zwięźle:
Operator Bang nakazuje kompilatorowi tymczasowe złagodzenie ograniczenia „nie zerowego”, którego w przeciwnym razie mógłby wymagać. Mówi do kompilatora: „Jako programista wiem lepiej od ciebie, że ta zmienna nie może być teraz zerowa”.
źródło
var
lublet
domyślnie zainicjowaneundefined
. Ponadto właściwości instancji klasy można zadeklarować jako takie, więcclass C { constructor() { this.myVar = undefined; } }
jest to całkowicie legalne. Wreszcie haki cyklu życia zależą od struktury; na przykład Angular i React wdrażają je inaczej. Dlatego nie można oczekiwać, że kompilator TS będzie o nich myślał.