背景
JavaScriptでは、typeof演算子は実行時にプリミティブ値の型を確認するために使用されます。TypeScriptはこのメカニズムを拡張し、型保護(type guards)を通じて型の絞り込み(type narrowing)の一部として扱います。TypeScriptは、typeof演算子の結果を利用して、コードブロック内の変数の型を明確にし、特にユニオン型を扱う際に関数のロジックをより正確に記述させます。
問題
通常のJavaScriptでは、typeofを使用して値の型を確認した後、型の保証はありません。プログラマーは、コードのどの部分で何が起こるかを記憶しておく必要があります。しかし、TypeScriptでは、異なる型やユニオン型が存在するため、適切に型を絞り込まないと、存在しないメソッドにアクセスするなどの誤りを犯しやすくなります。また、演算子には具体的な制約があります。基本的なプリミティブ型しか「見る」ことができず、配列やオブジェクトの場合は常に'object'を返します。
解決策
TypeScriptでは、typeof演算子を独自の型分析と組み合わせて、コードブロック内の変数の型を絞り込むことができます。これにより、セキュリティが自動的に向上します。コンパイラは、コードがどの型で動作しているかを把握し、可能なプロパティやメソッドを提示します。
コード例:
function printId(id: number | string) { if (typeof id === 'string') { // このブランチ内ではid: string console.log(id.toUpperCase()); } else { // このブランチ内ではid: number console.log(id.toFixed(2)); } }
主な特徴:
typeof演算子で配列を特定できますか?
いいえ、配列とオブジェクトのtypeofは同じ値—'object'を返します。配列を特定するには、Array.isArray()メソッドを使用する方が良いです。
コード例:
const arr = [1, 2, 3]; console.log(typeof arr); // 'object' console.log(Array.isArray(arr)); // true
typeofでnullとオブジェクトを区別できますか?
いいえ、typeof nullは'object'を返します。これはJavaScriptの歴史的な特徴です。
コード例:
console.log(typeof null); // 'object'
typeofを使ってユーザークラスを確認できますか?
いいえ、クラスのインスタンスに対してtypeofは'object'を返します。この場合はinstanceof演算子やユーザー定義の型ガード関数を使います。
コード例:
class User {} const u = new User(); console.log(typeof u); // 'object' console.log(u instanceof User); // true
typeofを使用すること。instanceofやArray.isArray()演算子を使用しないこと。プログラマーが、typeofを使ってvalueが配列かどうかを確認し、その結果に基づいて異なるメソッドを呼び出そうとした関数を書きました。
利点:
欠点:
Array.isArrayを使用し、型ガードと組み合わせる。
利点:
欠点: