altJS、すなわち、JavaScriptの代わりとなる言語の筆頭である「TypeScript」。TypeScriptという言語名が示す通り、JavaScriptに「Type」、つまり、型の概念を持ち込んだものです。本連載では、このTypeScriptの型に関して、さまざまな方向から紹介していきます。前回は関数の型に関して、基本となる引数や戻り値の型、さらには関数そのものの型を紹介しました。今回は引き続き、関数の型を掘り下げていき、型ガードやオーバーロードなどを紹介します。
この記事は会員限定です。会員登録(無料)すると全てご覧いただけます。
連載の第2回では、ユニオン型変数、すなわち、複数のデータ型に対応した変数を紹介しました。このユニオン型は、関数の引数として指定できます。具体例を見ていきましょう。
例えば、名前を表す文字列、または、年齢を表す数値という引数を基に、何かメッセージを生成する関数createMessage()があるとします。この関数のシグネチャは、リスト1のようになります。
function createMessage(nameOrAge: string|number): string
このシグネチャのポイントは、引数のデータ型として「string|number」のようにユニオン型を指定したところです。こうすることで、リスト2のように、文字列、数値の両方を渡せるようになりました。
const msg1 = createMessage("田中太郎"); const msg2 = createMessage(25);
一方で、stringとnumber以外のデータ型の引数は渡せません。試しに、boolean型の引数を渡そうとすると、図1のようにエラーになります(以下、「Visual Studio Code」を利用)。
ここで、リスト2の実行結果として、msg1は「田中太郎さん!ようこそ!」、msg2は「25歳おめでとう!」になるとします。そのようにcreateMessage()関数を作ろうとするならば、当然、引数のデータ型がstringなのかnumberなのか、関数内で分岐させる仕組みが必要になります。その上で、string型なら、引数に「さん!ようこそ!」を追加した文字列を戻り値にします。一方、number型なら、「歳おめでとう!」を追加した文字列にします。
このように、データ型で分岐する際に活躍する演算子が、「typeof」です。typeofを用いたcreateMessage()関数はリスト3のようになります。
function createMessage(nameOrAge: string|number): string { let message = ""; if(typeof nameOrAge == "string") { // (1) message = `${nameOrAge}さん!ようこそ!`; } else { // (2) message = `${nameOrAge}歳おめでとう!`; } return message; }
リスト3(1)のif条件式の中で、引数nameOrAgeに対してtypeof演算子を適用しています。このtypeof演算子の演算結果は、以下のいずれかの文字列になり、それぞれが該当するデータ型を表します。
・string
・number
・bigint
・boolean
・symbol
・undefined
・object
・function
typeofを利用して型判定を行う構文は、次の通りです。
[構文1]typeofによる型判定 typeof 変数 == "データ型文字列"
前項で紹介したtypeof演算子は、TypeScript独自のものではなく、JavaScriptにもあります。しかし、TypeScriptではtypeofに別の利点があります。typeofで型判定を行った条件分岐ブロック内では、該当変数はその型に固定される、という利点です。これを、「型ガード」といいます。
例えば、リスト3の(1)の条件に合致するブロック内では、nameOrAgeはstring型として振る舞います。そのため、例えば文字数を取得するリスト4のコードは問題なく実行できます。
const length = nameOrAge.length;
一方で、掛け算を実行するリスト5のコードは、型ガードのため、図2のようにエラーになります。
const months = nameOrAge * 12;
一方、リスト3(2)のelseブロックでは、nameOrAgeはnumber型として振る舞うので、逆に、リスト4はエラーになり、リスト5は問題なく動作します(図3)。
typeofによる型ガードを使うと、引数などで、どうしても複数のデータ型をまとめて扱わなければならない場合でも、安心してコーディングできます。
ところで、typeof演算子の演算結果を見ると、オブジェクトが全てobject型になってしまいます。オブジェクトの型を区別したい場合は、typeofではなく、「instanceof」演算子を使います。ただし、typeofとは使い方が違います。
具体例を見てみましょう。例えば、リスト6のようなシグネチャの関数があるとします。
Copyright © ITmedia, Inc. All Rights Reserved.