メインコンテンツにスキップ
モジュール 5 · レッスン 1 / 2コース内の 9/14~15 min
モジュールのレッスン (1/2)

タイプガード

型の絞り込みは、TypeScript の最も重要な概念の 1 つです。ただし、typeof や instanceof などの標準の型ガードでは、複雑なカスタム オブジェクトには不十分なことがよくあります。ここで カスタム タイプ ガード が役に立ちます。

標準タイプのガード

まずは、TypeScript が標準の JavaScript 演算子を使用して型を絞り込む方法を要約します。

TS
function processInput(val: string | number) {
  if (typeof val === 'string') {
    // Here 'val' is of type string
    console.log(val.toUpperCase());
  } else {
    // Here 'val' is of type number
    console.log(val.toFixed(2));
  }
}

カスタム タイプ ガード (is 演算子)

カスタムの型ガードを定義するには、標準のブール戻り値の型の代わりに、型述語を parameterName is Type 形式で返す関数を作成します。

関数はブール値 (true または false) を返す必要があります。 true が返された場合、TypeScript は渡されたパラメーターが指定された型であることを認識します。

TS
interface Cat {
  name: string;
  meow(): void;
}

interface Dog {
  name: string;
  bark(): void;
}

// This is a custom type guard
function isCat(animal: Cat | Dog): animal is Cat {
  return (animal as Cat).meow !== undefined;
}

function makeNoise(pet: Cat | Dog) {
  if (isCat(pet)) {
    // Here TypeScript knows 'pet' is a Cat
    pet.meow();
  } else {
    // Here TypeScript knows 'pet' is a Dog
    pet.bark();
  }
}

安全性とキャスト (as とタイプ ガード)

型キャスト (val as Cat など) は、実際の実行時検証を行わずに、コンパイラーに開発者を信頼することを強制します。ランタイム オブジェクトが期待を満たさない場合、コードは通知なしで失敗するか、例外をスローします。

一方、カスタム型ガードは、堅牢かつ動的なランタイム チェックを実行し、TypeScript コンパイラーに実際の変数の型を安全かつ正確に通知します。

TS
function processInput(input: unknown) {
  // unsafe casting: could crash if input does not have the split method
  // const str = input as string;
  // console.log(str.split(' '));

  // safe guard
  if (isString(input)) {
    console.log(input.split(' ')); // 100% Safe!
  }
}

自分で試してみてください

演習 1: 文字列型ガード

運動#ts.m5.l1.e1
試行回数: 0読み込み中…

不明な値が文字列であるかどうかを確認するカスタム タイプ ガードとして機能する isString という名前の単純な関数を作成します。

エディターを読み込み中…
ヒントを表示

関数の戻り値の型は val is string である必要があり、typeof を使用してそれが 'string' に等しいかどうかを確認する必要があります。

3 回の試行後に解決策が利用可能になります

演習 2: プレミアム ユーザー タイプ ガード

運動#ts.m5.l1.e2
試行回数: 0読み込み中…

User タイプと PremiumUser タイプを指定して、ユーザーが「プレミアム」ロールを持っているかどうかを確認するタイプ ガード関数 isPremiumUser(user: User): user is PremiumUser を作成します。

エディターを読み込み中…
ヒントを表示

署名を関数 isPremiumUser(user: User): user is PremiumUser として定義し、user.role を「premium」と比較します。

3 回の試行後に解決策が利用可能になります

演習 3: カスタム エラー オブジェクトの検証

運動#ts.m5.l1.e3
試行回数: 0読み込み中…

isCustomError(err:unknown):err は、不明な値が「code」キーを含む null 以外の CustomError オブジェクトであるかどうかを検証する CustomError 関数です。

エディターを読み込み中…
ヒントを表示

まず、typeof err が 'object' であり、null ではないかどうかを確認し、次に 'in' 演算子を使用して 'code' プロパティを確認します。

3 回の試行後に解決策が利用可能になります

演習 4: 管理者タイプ ガード

運動#ts.m5.l1.e4
試行回数: 0読み込み中…

User (プロパティ role: string) と Admin (User を拡張し、プロパティ adminToken: string を持つ) という 2 つのインターフェイスがある場合、User 型のユーザーを受け入れ、型述語 user is Admin を返す isAdmin という名前の型ガード関数を作成します。ガードは、ユーザーのロールが「admin」と等しいかどうかを確認する必要があります。

エディターを読み込み中…
ヒントを表示

署名を関数 isAdmin(user: User): user is Admin として定義し、user.role === 'admin' かどうかを確認します。

3 回の試行後に解決策が利用可能になります