はじめに
TypeScriptを業務で触り始めて2年経ちました。
「型って何?」というところから始まって、ある程度は書けるようになったものの、未だにコードを読んでて「?」となる事もあります。
最近は勉強会などで色んな人のLTのスライドを見た時に知らなかったことを記事にしました。
非Nullアサーション
変数の後に!
があるのを非Nullアサーションといいます。
変数やプロパティの値がnullまたはundefinedではないことを保証するための記法です。
コンパイラに対して「ここではnullやundefinedは発生しないよ」と明示することで、型エラーを回避できます。
let num: number;
initNum();
console.log(num! * 2); // エラーにならない
// 非Nullアサーション
function initNum() {
num = 2;
}
初めてそれを見た時「え…論理演算子じゃないよね…?」ってなりました。
問題点
明確な割り当てアサーションと非Nullアサーションは、型の安全性を保証する責任をコンパイラからプログラマに移すものです。そして、型に関してはコンパイラより人間のほうがミスをしやすいです。なので、こうしたアサーションはできる限り使わないほうが安全性は高いです。
(サバイバルTypeScriptより)
つまりコンパイル時には問題なくても実行時にうまく動かない可能性があるので使わないほうが良さそうです。
型アサーション
TypeScriptには、型推論を上書きする機能があります。その機能を型アサーション(type assertion)と言います。
TypeScriptコンパイラーはコードをヒントに型を推論してくれます。その型推論は非常に知的ですが、場合によってはコンパイラーよりもプログラマーがより正確な型を知っている場合があります。そのような場合は、型アサーションを用いるとコンパイラーに型を伝えることができます。型アサーションはコンパイラに「私を信じて!私のほうが型に詳しいから」と伝えるようなものです。
const user:unknown = 'HANAKO'
console.log(user as number)
上記のコードは当然エラーになります。
実際の型と異なる場合でも強制的に型変換が可能になってしまうので、実行時エラーになるようです。
では下記のコードはどうでしょう。
const user:string = 'HANAKO'
console.log(user as number)
サバイバルTypeScriptにも 「型アサーションはコンパイラーの型推論を上書きできるとは言っても、無茶な型の変換はできないようになっています」 と書いてあるようにTypeScript Playgroundで実際のコードを書いてみたところ以下のようなエラーが表示されました。
Conversion of type 'string' to type 'number' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
まとめ
非Nullアサーションも型アサーションも積極的に使わないほうが良さそうなのは理解できました。
参考