【イラスト付き】型の判断【丁寧に解説】

2024/09/04に公開

はじめに

皆さんこんにちは。
今回はTypeScriptでの型の判断方法をご紹介します。

TypeScriptは型を利用した安全なコーディングができます。そのため型を明確にしないとコンパイルエラーになることがあります。そこで値の型を判断する方法があります。今回はTypeScriptでの型の判断方法についてご紹介します。

こんな人にオススメ

  • TypeScriptの型ガードの書き方を知りたい
  • TypeScriptの型アサーションの書き方を知りたい

初めて学習する方にも分かるように、丁寧に解説していきます。
すでに利用されている方も、是非一度目を通していただけると嬉しいです。

😋 TypeScriptの型の判断方法をご紹介します♪

型ガード

まずポイントをチェック

  • 扱う変数の型をチェックし安全に扱う
  • if文で判断する
    • typeofで特定の型かチェック
    • instanceofで特定のクラス型かチェック
    • inで特定のプロパティを持つかチェック

型ガードとは、値の型が条件に合うものか確認する方法です。型を絞り込むことで安全に値を使うことができます。

また、特定の型のみが持つプロパティやメソッドを利用する際や、nullの可能性がある値は、型ガードで絞り込みを行わないとコンパイルエラーになります。

nullチェック

nullチェックは通常のプログラミング通りif文で行います。

TypeScript/05.judge-type/app.ts(nullチェックのみ抜粋)

// 型ガード(nullではないことをチェック)
// 戻り値がnullかもしれない関数の宣言と実行
const getTitle = (): string | null => 'abc';
const title: string | null = getTitle();

// titleはnullかもしれないのでコンパイルエラー
// console.log(title.toUpperCase());

// nullではないことを保証すればOK
if (title) {
    console.log(title.toUpperCase());
}

typeofで特定の型かチェック

string型やnumber型であることをチェックしたい場合はtypeofを使います。typeofを使うと値の型名を文字列で取得することができます。

TypeScript/05.judge-type/app.ts(typeofのみ抜粋)

// 型ガード(typeofでstringであることをチェック)
// 戻り値がstringかnumberの関数の宣言と実行
const getValue = (): string | number => 'abc';
const value: string | number = getValue();

// valueはnumberかもしれないのでコンパイルエラー
// console.log(value.toUpperCase());

// stringであることを保証すればOK
if (typeof value === 'string') {
    console.log(value.toUpperCase());
}

instanceofで特定のクラス型かチェック

扱うオブジェクトが特定のクラスから生成されたインスタンスであることをチェックしたい場合はinstanceofを使います。

TypeScript/05.judge-type/app.ts(instanceofのみ抜粋)

// 型ガード(instanceofでBook型であることをチェック)
class Car { }
class Book {
    private title: string;
    private price: number;
    constructor(title: string, price: number) {
        this.title = title;
        this.price = price;
    }
    showInfo() {
        console.log(`${this.title}(${this.price})`);
    }
}
// Bookクラス型とCarクラス型の両方を受け取れる関数宣言
const fn1 = (obj: Book | Car) => {
    // Carクラス型にはshowInfoメソッドはないのでコンパイルエラー
    // obj.showInfo();

    // Bookクラス型であることを保証すればOK
    if (obj instanceof Book) {
        obj.showInfo();
    }
};

inで特定のプロパティを持つかチェック

扱うオブジェクトが特定のプロパティを持つかチェックしたい場合はinを使います。

TypeScript/05.judge-type/app.ts(inのみ抜粋)
// 型ガード(inでpriceプロパティを持つことをチェック)
interface Book1 { title: string; price: number };
interface Book2 { title: string; };
// priceプロパティを持たないオブジェクトも受け取れる関数宣言 
const fn2 = (obj: Book1 | Book2) => {
    // Book2型にはpruceはないのでコンパイルエラー
    // console.log(obj.price);

    // priceを持つことを保証すればOK
    if ('price' in obj) {
        console.log(obj.price);
    }
};

😋 typeof, in, instanceofで値をチェックします♪

型アサーション

まずポイントをチェック

  • コンパイラに対して型を手動で指定
  • コンパイラによる型チェックを放棄
    • プログラマの責任で指定する
  • as で特定の型であると指定

型アサーションとはコンパイラに対して型を明示する方法です。これによりコンパイラが推論した型とは異なる型を無理やり指定することができます。

型アサーションはコンパイラによるの型チェックを放棄し、プログラマが責任を持つことになります。そのためTypeScriptのメリットである型による安全なコーディングではなくなります。

型アサーションはasキーワードで行います。asの右側に型を指定します。

下記の例は、戻り値がnullの可能性がある関数を実行していますが、型アサーションで戻り値をstring型であると明示しています。これによりnullチェックが不要になります。

TypeScript/05.judge-type/app.ts(型アサーションでnullではないことを明示のみ抜粋)
// 型アサーション(stringであること(nullではないこと)を明示)
// 戻り値がnullかもしれない関数の宣言と実行
const getTitle2 = (): string | null => 'abc';
const title2: string | null = getTitle() as string; // 型アサーション
console.log(title2.toUpperCase()); // 型ガード不要

下記の例は、戻り値がstring型かnumber型の可能性がある関数を実行していますが、型アサーションで戻り値をstring型であると明示しています。これによりstring型であるかのチェックが不要になります。

TypeScript/05.judge-type/app.ts(型アサーションでnumberではないことを明示のみ抜粋)
// 型アサーション(stringであること(numberではなこと)を明示)
// 戻り値がstringかnumberの関数の宣言と実行
const getValue2 = (): string | number => 'abc';
const value2: string | number = getValue() as string; // 型アサーション
console.log(value2.toUpperCase()); // 型ガード不要

下記の例は、引数がBookクラス型かCarクラス型の可能性がある関数宣言です。引数で受け取った値を型アサーションでBookクラス型であると明示しています。これによりBookクラス型であるかのチェックが不要になります。

TypeScript/05.judge-type/app.ts(型アサーションでBookクラス型であることを明示のみ抜粋)
// 型アサーション(Bookであることを明示)
// Bookクラス型とCarクラス型の両方を受け取れる関数宣言
const fn3 = (obj: Book | Car) => {
    const book = obj as Book; // 型アサーション
    book.showInfo(); // 型ガード不要
};

下記の例は、引数のオブジェクトがpriceプロパティを持たない可能性がある関数宣言です。引数で受け取った値を型アサーションでBook1型であると明示しています。これによりpriceプロパティを持つことが保証されチェックが不要になります。

TypeScript/05.judge-type/app.ts(型アサーションで特定のプロパティを持つ型であることを明示のみ抜粋)
// 型アサーション(Book1であることを明示)
// priceプロパティを持たないオブジェクトを受け取るかもしれない関数宣言
const fn4 = (obj: Book1 | Book2) => {
    const book = obj as Book1; // 型アサーション
    console.log(book.price); // 型ガード不要
};

😋 コンパイラに型を明示し型チェックから逃れます♪

おわりに

皆さん、お疲れ様でした。
ここまでご覧いただき、ありがとうございました。

型の判断方法について確認をしていただきました。
TypeScriptでは型ガードを使って利用する値の型を判断できます。
また型アサーションでを使うことで型をコンパイラに明示することができます。

😋 これからもプログラミング学習頑張りましょう♪

参考リンク集(MDN Web Docs のリンク)
参考リンク集(サンプルコード)

Discussion