Generics 型とは
- 追加の型情報を提供できる型です
- TypeScriptの型安全を高めたコードを書けます
- IDEの自動補完サポートなどが受けられます
Array<string>
Array<number>
##型の指定方法
const names: any[] = [];
const names: Array<string> = []; // string[]
const names: Array<string | number> = []; // string[]
const names: Array<any> = []; // string[]
//この配列ではstringの操作が可能
const names: Array<string> = []; // string[]
names[0].split(' ');
###Promiseコンストラクタ関数で型を指定
- Promiseと指定することで、最終的にnumberを返す関数であることを明示的にできる
const promise: Promise<string> = new Promise((resolve, reject) => {
setTimeout(() => { //timer設定
resolve('終わり!'); //stringを返す
}, 2000);
});
// Generics型 <string>を使えば、stringメソッドを呼べる
promise.then(data => {
data.split(' ');
});
##独自のGenerics関数を作成
- 関数の引数に object型を指定するのみでは、objectの中身のプロパティ情報が得られません
merge(objA: object, objB: object)
- 型キャストをつかって、型情報を指定することができるが、1個1個指定するのは大変。。
- Generics型を使えば、特定の異なった型の交差型を渡すと伝えることができ、明確に型を指定しなくても、オブジェクトのプロパティ情報を伝えることができます
- つまり、関数の引数から動的に型を設定することができ、柔軟な関数になります!
//objectとobjectの交差型を返す
function merge(objA: object, objB: object) {
return Object.assign(objA, objB);
}
console.log( merge( { name: 'Neko' } , { age: 3 } ) );
//変数に格納すると、name,ageのプロパティにアクセスできない
const mergedObj = merge( { name: 'Neko' } , { age: 3 } );
// console.log(mergedObj.age); // Property 'age' does not exist on type 'object'.
//対処法1 型キャストを使った場合
const mergedObj = merge( { name: 'Neko' } , { age: 3 } ) as {
name: string ;
age: number;
};
mergedObj.name ; //OK
//対処法2 Generics関数を使った場合
function merge<T , U>(objA: T, objB: U) { //交差型(T&U)を返すと推論される
return Object.assign(objA, objB);
}
const mergedObj = merge({ name: 'Neko', hobbies: ['Sports'] }, { age: 3 });
console.log(mergedObj.name); // Neko
//このように指定するのと同じこと(指定する必要はない)
const mergedObj = merge<{ name:string; hobbies :string[] }, {age: number}>(
{ name: 'Neko', hobbies: ['Sports'] },
{ age: 3 },
);
// Generics関数では、型を指定する必要がない
function merge<T , U>(objA: {name: string}, objB: U) { //交差型(T&U)を返すと推論される
return Object.assign(objA, objB);
}
//string以外を渡すとエラーになってしまう
const mergedObj = merge({ name: 'Max', hobbies: ['Sports'] }, { age: 30 }); // Argument of type '{ name: string; hobbies: string[]; }' is not assignable to parameter of type '{ name: string; }'.
Generics型 と Union型の違い
- Generics型:クラス全体で特定の型を固定して受け取ることができます
- Union型:関数が呼ばれたときに、毎回いづれかの型を受け取る時に使う 呼び出す毎に型を変更する柔軟性が必要な場合、Union型を使います
//Union型を使った場合
class DataStorage{ //ある特定の型のみを受け取りたい
//private data: (string | number | boolean)[] = []; //3つの型がミックスされてしまう書き方
private data: string[] | number[] | boolean[] = []; //いづれかの配列を受け取る
addItem(item: string | number | boolean ) { //関数が呼ばれた時に、どの型でも受け取ってしまう
this.data.push(item);
}
}