TypeScriptの型ガード

概要: このチュートリアルでは、TypeScriptにおける型ガードを使用して、変数の型を絞り込む方法を学びます。

型ガードを使用すると、条件ブロック内で変数の型を絞り込むことができます。

typeof

次の例を見てみましょう。

type alphanumeric = string | number;

function add(a: alphanumeric, b: alphanumeric) {
    if (typeof a === 'number' && typeof b === 'number') {
        return a + b;
    }

    if (typeof a === 'string' && typeof b === 'string') {
        return a.concat(b);
    }

    throw new Error('Invalid arguments. Both arguments must be either numbers or strings.');
}
Code language: TypeScript (typescript)

仕組み

  • まず、文字列または数値のいずれかを保持できるalphanumeric型を定義します。
  • 次に、alphanumeric型の2つの変数abを加算する関数を宣言します。
  • 次に、typeof演算子を使用して、両方の引数の型が数値であるかどうかを確認します。もしそうであれば、+演算子を使用して引数の合計を計算します。
  • その後、typeof演算子を使用して、両方の引数の型が文字列であるかどうかを確認します。もしそうであれば、2つの引数を連結します。
  • 最後に、引数が数値でも文字列でもない場合はエラーをスローします。

この例では、TypeScriptは条件ブロックでのtypeof演算子の使用法を認識しています。次のifブロック内では、TypeScriptはabが数値であることを認識します。

if (typeof a === 'number' && typeof b === 'number') {
    return a + b;
}Code language: TypeScript (typescript)

同様に、次のifブロックでは、TypeScriptはabを文字列として扱い、したがってそれらを1つに連結することができます。

if (typeof a === 'string' && typeof b === 'string') {
    return a.concat(b);
}
Code language: TypeScript (typescript)

instanceof

typeof演算子と同様に、TypeScriptはinstanceof演算子の使用法も認識しています。例:

class Customer {
    isCreditAllowed(): boolean {
        // ...
        return true;
    }
}

class Supplier {
    isInShortList(): boolean {
        // ...
        return true;
    }
}

type BusinessPartner = Customer | Supplier;

function signContract(partner: BusinessPartner) : string {
    let message: string;
    if (partner instanceof Customer) {
        message = partner.isCreditAllowed() ? 'Sign a new contract with the customer' : 'Credit issue';
    }

    if (partner instanceof Supplier) {
        message = partner.isInShortList() ? 'Sign a new contract the supplier' : 'Need to evaluate further';
    }

    return message;
}
Code language: TypeScript (typescript)

仕組み

  • まず、CustomerクラスとSupplierクラスを宣言します。
    次に、CustomerSupplierの共用体型である型エイリアスBusinessPartnerを作成します。
  • 3番目に、BusinessPartner型のパラメータを受け取る関数signContract()を宣言します。
  • 最後に、パートナーがCustomerまたはSupplierのインスタンスであるかどうかを確認し、それぞれのロジックを提供します。

次のifブロック内では、TypeScriptは、instanceof演算子のため、パートナーがCustomer型のインスタンスであることを認識します。

if (partner instanceof Customer) {
    message = partner.isCreditAllowed() ? 'Sign a new contract with the customer' : 'Credit issue';
}Code language: TypeScript (typescript)

同様に、TypeScriptは、次のifブロック内でパートナーがSupplierのインスタンスであることを認識します。

if (partner instanceof Supplier) {
    message = partner.isInShortList() ? 'Sign a new contract with the supplier' : 'Need to evaluate further';
}Code language: TypeScript (typescript)

if文で1つの型が絞り込まれると、TypeScriptはelse文の中ではそれがその型ではなく、別の型であることを認識します。例:

function signContract(partner: BusinessPartner) : string {
    let message: string;
    if (partner instanceof Customer) {
        message = partner.isCreditAllowed() ? 'Sign a new contract with the customer' : 'Credit issue';
    } else {
        // must be Supplier
        message = partner.isInShortList() ? 'Sign a new contract with the supplier' : 'Need to evaluate further';
    }
    return message;
}
Code language: TypeScript (typescript)

in

in演算子は、オブジェクトのプロパティの存在を安全にチェックします。型ガードとしても使用できます。例:

function signContract(partner: BusinessPartner) : string {
    let message: string;
    if ('isCreditAllowed' in partner) {
        message = partner.isCreditAllowed() ? 'Sign a new contract with the customer' : 'Credit issue';
    } else {
        // must be Supplier
        message = partner.isInShortList() ? 'Sign a new contract the supplier ' : 'Need to evaluate further';
    }
    return message;
}
Code language: TypeScript (typescript)

ユーザー定義型ガード

ユーザー定義型ガードを使用すると、型ガードを定義したり、関数を使用する際にTypeScriptが型を推論するのに役立ちます。

ユーザー定義型ガード関数は、単にarg is aTypeを返す関数です。例:

function isCustomer(partner: any): partner is Customer {
    return partner instanceof Customer;
}
Code language: TypeScript (typescript)

この例では、isCustomer()はユーザー定義の型ガード関数です。これで、次のように使用できます。

function signContract(partner: BusinessPartner): string {
    let message: string;
    if (isCustomer(partner)) {
        message = partner.isCreditAllowed() ? 'Sign a new contract with the customer' : 'Credit issue';
    } else {
        message = partner.isInShortList() ? 'Sign a new contract with the supplier' : 'Need to evaluate further';
    }

    return message;
}
Code language: TypeScript (typescript)

まとめ

  • 型ガードは、条件ブロック内で変数の型を絞り込みます。
  • 条件ブロックで型ガードを実装するには、typeof演算子とinstanceof演算子を使用します。
このチュートリアルは役に立ちましたか?