TypeScript ジェネリック制約

概要: このチュートリアルでは、TypeScript のジェネリック制約について学習します。

TypeScript におけるジェネリック制約の概要

以下の例を考えてみましょう。

function merge<U, V>(obj1: U, obj2: V) {
    return {
        ...obj1,
        ...obj2
    };
}Code language: TypeScript (typescript)

merge() は 2 つのオブジェクトをマージするジェネリック関数です。たとえば、

let person = merge(
    { name: 'John' },
    { age: 25 }
);

console.log(result);Code language: TypeScript (typescript)

出力

{ name: 'John', age: 25 }Code language: TypeScript (typescript)

完璧に機能します。

merge() 関数は 2 つのオブジェクトを想定しています。しかし、次のようにオブジェクト以外のものを渡すこともできます。

let person = merge(
    { name: 'John' },
    25
);

console.log(person);Code language: TypeScript (typescript)

出力

{ name: 'John' }Code language: TypeScript (typescript)

TypeScript はエラーを発行しません。

すべての型を扱うのではなく、merge() 関数に制約を追加して、オブジェクトでのみ機能するようにすることもできます。

これを行うには、U 型と V 型が許容されるものに対する制約として要件をリストする必要があります。

制約を表すには、extends キーワードを使用します。たとえば、

function merge<U extends object, V extends object>(obj1: U, obj2: V) {
    return {
        ...obj1,
        ...obj2
    };
}
Code language: TypeScript (typescript)

merge() 関数が制約されるようになったため、すべての型で動作しなくなりました。代わりに、object 型でのみ動作します。

以下ではエラーが発生します。

let person = merge(
    { name: 'John' },
    25
);Code language: TypeScript (typescript)

エラー

Argument of type '25' is not assignable to parameter of type 'object'.Code language: TypeScript (typescript)

ジェネリック制約で型パラメータを使用する

TypeScript では、別の型パラメータによって制約された型パラメータを宣言できます。

次の prop() 関数は、オブジェクトとプロパティ名を受け入れます。プロパティの値を返します。

function prop<T, K>(obj: T, key: K) {
    return obj[key];
}Code language: TypeScript (typescript)

コンパイラは次のエラーを発行します。

Type 'K' cannot be used to index type 'T'.Code language: TypeScript (typescript)

このエラーを修正するには、K に制約を追加して、T のキーであることを確認します(次のように)。

function prop<T, K extends keyof T>(obj: T, key: K) {
    return obj[key];
}Code language: TypeScript (typescript)

obj に存在するプロパティ名を prop 関数に渡すと、コンパイラはクレームしません。たとえば、

let str = prop({ name: 'John' }, 'name');
console.log(str);Code language: TypeScript (typescript)

出力

JohnCode language: TypeScript (typescript)

ただし、最初の引数に存在しないキーを渡すと、コンパイラはエラーを発行します。

let str = prop({ name: 'John' }, 'age');Code language: TypeScript (typescript)

エラー

Argument of type '"age"' is not assignable to parameter of type '"name"'.Code language: TypeScript (typescript)

概要

  • extends キーワードを使用して、型パラメータを特定の型に制約します。
  • extends keyof を使用して、別のオブジェクトのプロパティである型を制約します。
このチュートリアルは役立ちましたか?