4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【TypeScript】TypeScript の Generics

Posted at

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);
  }

}
4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?