typescriptの型アサーションについて

typescriptで型アサーションが出てきて「??」となったのが解決したので書き残します。自分の中で納得する答えを出しただけなので、もしかしたら間違っているかもしれませんがその時は指摘していただけるとありがたいです。

型アサーションは例えば下のようなサンプルのコードと「型キャスト」なる単語とセットで説明してありました。

let val1: any = "abcde";
let len1: number = (val1 as string).length;

型キャストを知らなかった私はすぐに調べました。大抵の記事は、文字型の"10"を数値型の10にするように型を変換することを型キャストと書いてありました。なので次のようなコードを試してみるとエラーが返ってきました。

let num: number = 777;
let numString: string = num as string;

つまり数値型から文字型には変換できないようです(ちなみに規則の緩いanyからstringやnumber、またはその逆は可能です)。

そうなんです。型アサーションは型を変換するのではなく、コンパイラに対して「私はこの変数の型をちゃんとチェックしたので無視していいですよ!」と宣言するものなのです。

例えば次のような場合は数値を代入しているので文字列型ではありません。よってアルファベットを大文字に変換するtoUpperCase()は使えません。なのでコンパイラが型を判断してコンパイルの次点でエラーにしてくれます。

const num = 777
num.toUpperCase() // コンパイルエラー

しかし、次のように型アサーションで型の規則が緩いany型で宣言するとany型に対しては文字列型の可能性もあるのでtoUpperCase()が使えます。型アサーションを宣言しているので変数の中についてコンパイル時には厳密なチェックは行わず、なのでコンパイルの時はエラーを返さず実行時にエラーが返ってきます。

const num = 777 as any
num.toUpperCase() // コンパイルは成功するものの実行時にエラー

こうなってくると型アサーションの存在意義がわからなくなってきますが、よく使われるのはjavaScriptで書いたコードを移植する時みたいです。これに関しては私が理解できていない部分がまだ多いため具体例は出さないことにします。

余談

下のような感じでany →stringと型アサーションを宣言するとコンパイラを騙してstring型の変数に数値をいれることができます。

let num: number = 777;
let numString: string = (num as any) as string;
alert(typeof numString); // 実行結果:number

しかし、typescriptにおいてコンパイラは厳密性を高めるものなので騙したところで実行時エラーを引き起こすだけです。実際コンパイルで変換されたjavascriptのコードは以下の通りでtypeofではnumberが返ってきます。

let num = 777;
let numString = num;
alert(typeof numString); // 実行結果:number

いろいろな記事で型アサーションは避けるべきと書いてあります。もしかしたらここまで掘り下げる必要はないトピックだったかもしれません。

この記事が気に入ったらサポートをしてみませんか?