En caractères d'imprimerie, ce qui est la ! (point d'exclamation) de l'opérateur lors de la référence à un membre?
Lorsque l'on regarde le code source pour un tslint la règle, je suis tombé sur la déclaration suivante:
if (node.parent!.kind === ts.SyntaxKind.ObjectLiteralExpression) {
return;
}
Avis de la !
opérateur après node.parent
. Intéressant!
J'ai d'abord essayé de compiler le fichier en local avec ma version actuellement installée de TS (1.5.3). L'erreur qui en résulte a souligné l'emplacement exact de la bang:
$ tsc --noImplicitAny memberAccessRule.ts
noPublicModifierRule.ts(57,24): error TS1005: ')' expected.
Ensuite, j'ai mis à niveau vers la dernière TS (2.1.6), qui a compilé sans problème. De sorte qu'il semble être caractéristique de TS 2.x. Mais la transpilation ignoré le bang complètement, résultant dans la suite de JS:
if (node.parent.kind === ts.SyntaxKind.ObjectLiteralExpression) {
return;
}
Mon Google-fu a jusqu'à présent échoué à moi.
Qu'est-ce que TS du point d'exclamation opérateur, et comment ça fonctionne?
OriginalL'auteur Mike Chamberlain | 2017-02-16
Vous devez vous connecter pour publier un commentaire.
C'est la non-nulle affirmation de l'opérateur. C'est une façon de dire au compilateur "cette expression ne peut pas être
null
ouundefined
ici, alors ne vous plaignez pas de la possibilité d'êtrenull
ouundefined
." Parfois, le type de correcteur est pas en mesure de procéder à cette détermination elle-même.Il est expliqué ici:
Je trouve l'utilisation du terme "imposer" un peu trompeur dans cette explication. Il est "d'affirmer" dans le sens que le développeur est le faire valoir, non pas dans le sens d'un test va être effectué. La dernière ligne indique en effet qu'il en résulte aucun code JavaScript émis.
Bonne explication. Je trouve ça une bonne pratique de faire un
console.assert()
sur la variable en question avant d'ajouter un!
après. Car ajouter!
est de dire au compilateur d'ignorer la valeur null est à vérifier, il compile à noop en javascript. Donc, si vous n'êtes pas sûr que la variable est non nulle, alors vaut mieux le faire explicitement affirmer vérifier.Comme un exemple motivant: à l'aide de la nouvelle ES le type de Carte avec un code comme
dict.has(key) ? dict.get(key) : 'default';
le TS compilateur ne peut pas en déduire que lesget
appel n'retourne null/undefined.dict.has(key) ? dict.get(key)! : 'default';
rétrécit le type correctement.OriginalL'auteur Louis
Louis réponse est génial, mais j'ai pensé que je voudrais essayer de le résumer en quelques mots:
Le bang opérateur indique au compilateur temporairement détendre le "not null" contrainte qu'elle pourrait autrement de la demande. Il dit au compilateur: "en tant Que développeur, je sais mieux que vous que cette variable ne peut pas être null droit maintenant".
Ensuite, en tant que développeur, vous avez foiré.
Ou, comme le compilateur, il a foiré. Si le constructeur n'a pas initialiser une propriété, mais un cycle de vie de crochet-t-il et le compilateur ne pas le reconnaître.
Ce n'est pas de la responsabilité de la TS compilateur. Contrairement à d'autres langues (par exemple. C#), JS (et, par conséquent, TS) ne demande pas que les variables sont initialisées avant de l'utiliser. Ou, pour regarder une autre façon, en JS toutes les variables déclarées avec
var
oulet
sont implicitement initialisé àundefined
. De plus, la classe des propriétés d'une instance peut être déclaré en tant que tel, de sorteclass C { constructor() { this.myVar = undefined; } }
est parfaitement légal. Enfin, le cycle de vie crochets de cadre à charge; par exemple Angulaire de Réagir et de mettre en œuvre différemment. Donc le TS compilateur ne peut pas être prévu à la raison sur eux.Utilisez un point d'interrogation à la place. par exemple,
private something?: MyComponent;
OriginalL'auteur Mike Chamberlain