TypeScriptジェネリックの使用

TypeScriptジェネリックの使用

序文:

JavaScriptは弱い型付けの言語であるため、 API をカプセル化するとさまざまな用途に使用できますが、弱い型付けによって得られる最終結果は、私たちが望むものではありません。

TypeScript の登場によりこの問題は解決しましたが、API の再利用を考えると、TypeScript はそれほど柔軟ではないようです。このとき、 any 型を使用すると柔軟性のなさという問題を解決できますが、JavaScript の問題に戻り、最終結果が期待どおりにならない可能性があります。

この問題を解決するために、 TypeScriptジェネリックの概念を導入しました。ジェネリックを使用すると、関数、インターフェース、またはクラスを定義するときに特定の型を事前に指定する必要がなくなり、代わりに使用時に型を指定できます。その目的は、コードをより広範囲に再利用することです。

1. 使いやすい

ここで、主に同じ型の 2 つの値を受け入れ、2 つのパラメーターの連結された値を返すjoin関数を定義する必要があります。サンプルコードは次のとおりです。

// いわゆるジェネリックは、より一般的な意味では、一般的に参照される型です。 // 同じ型の 2 つのパラメーターを受け入れ、連結された値を返す join 関数を定義します。
関数 join<T>(最初: T、2番目: T) {
  `${first}${second}` を返す
}
// ここで、T は文字列として指定されます typejoin<string>('第一', '第二') //第一第二// ここでは、型推論を通じて、コンパイラは渡されたパラメータに基づいて型を自動的に推論しますjoin(1, 2) // 12

ジェネリックは山括弧 <> を使用して定義されます。結合関数を定義するときに、どの型が受け入れられるかはわかりませんが、2 つの型が同じでなければならないことは確かです。このような要件を満たしたい場合、ジェネリックなしで解決するのはそれほど簡単ではありません。

関数を呼び出す場合、2 つの方法があります。1 つは型を文字列型として直接指定する方法、もう 1 つは型推論を使用する方法です。エディターは渡されたパラメーターに基づいて型を自動的に決定するのに役立ちます。

2. 関数内でジェネリックを使用する

関数を定義するときに、複数のジェネリックを使用することができ、数量と使用方法が対応している限り、戻り値の型もジェネリックを通じて指定できます。

サンプルコードは次のとおりです

関数の恒等式<T, Y, P>(1番目: T、2番目: Y、3番目: P): Y {
  2番目を返す
}
//指定された型 identity<boolean, string, number>(true, 'string', 123) // string // 型推論 identity('string', 123, true) // true

3. クラス内でジェネリックを使用する

ジェネリックは関数だけでなくクラスでも使用できます。

サンプルコードは次のとおりです。

クラスDataManager<T> {
  // T 型のプライベート配列を持つクラスを定義します。constructor(private data: T[]) {}
  // インデックスに基づいて配列内の値を取得します getItem(index: number): T {
    this.data[インデックス]を返す
  }
}
const data = new DataManager(['一碗周'])
data.getItem(0) // 周の一杯

さらに、ジェネリックはインターフェースから継承することもできます。サンプルコードは次のとおりです。

インターフェースアイテム{
  名前: 文字列
}
クラス DataManager<T extends Item> {
  // T 型のプライベート配列を持つクラスを定義します。constructor(private data: T[]) {}
  // インデックスに基づいて配列内の値を取得します getItem(index: number): string {
    this.data[index].nameを返す
  }
}
const data = new DataManager([{ name: '一碗周' }])
data.getItem(0) // 周の一杯

ジェネリック制約の効果を得るには、 extends使用します。上記のコードでは、渡された値が name 属性を持つように制約する必要があります。そうでない場合は、例外がスローされます。

4. ジェネリック制約における型パラメータの使用

次のような要件があるとします。いくつかのプロパティを含むプライベート オブジェクトを持つクラスを定義し、キーを通じて対応する値を取得するメソッドを定義します。

実装コードは次のとおりです。

// インターフェースを定義する interface Person {
  名前: 文字列
  年齢: 番号
  趣味: 弦楽器
}
// クラスを定義する class Me {
  コンストラクター(プライベート情報: Person) {}
  getInfo(キー: 文字列) {
    this.info[キー]を返す
  }
}
const me = 新しい Me({
  名前:「周の一杯」
  年齢: 18歳
  趣味:「コーディング」
})
// me.getInfo() を呼び出すと、未定義の値が返される可能性があります。たとえば、me.getInfo('myName') // undefined

上記のコードでは、インスタンス オブジェクトでgetInfo()メソッドを呼び出して、存在しないプロパティを渡すと、undefined が返されます。 undefined返すメソッドを呼び出すのはTypeScriptのスタイルではありません。

この問題は、特定の型のすべてのキーを取得するために使用できる keyof 演算子によって解決できます。その戻り値の型はユニオン型です。

サンプルコードは次のとおりです。

type myPerson = keyof Person // '名前' | '年齢' | '趣味'

これで、この演算子を使用して上記の問題を解決できます。

サンプルコードは次のとおりです。

クラスMe{
  コンストラクター(プライベート情報: Person) {}
  // これは getInfo<T extends keyof Person>(key: T): Person[T] { と同じです。
    this.info[キー]を返す
  }
  // getInfo<T extends 'name' | 'age' | 'hobby'>(key: T): Person[T] {
  // this.info[key]を返す
  // }
}
const me = 新しい Me({
  名前:「周の一杯」
  年齢: 18歳
  趣味:「コーディング」
})
// 不明なプロパティが渡された場合、me.getInfo() を呼び出すとコンパイル エラーが発生します。me.getInfo('myName') // エラー: '"myName"' 型の引数は、'keyof Person' 型のパラメーターに割り当てることはできません。

オブジェクトに存在しないプロパティにアクセスすると、コンパイルが異常になります。

TypeScript ジェネリックの使用に関するこの記事はこれで終わりです。TypeScript ジェネリックに関するその他の関連コンテンツについては、123WORDPRESS.COM で以前の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • TypeScript ジェネリックを簡単に説明する方法
  • TypeScript ジェネリックパラメータのデフォルト型と新しい厳密なコンパイルオプション
  • フロントエンドにおけるTypescriptの一般的な概念の深い理解
  • TypeScript のジェネリック使用法とジェネリックインターフェースの組み合わせ

<<:  MySQL における datetime と timestamp の違いと選択

>>:  CSSを使用してすべての子要素を選択する方法の詳細な説明

推薦する

Linuxサービスの監視と運用および保守

目次1. psutilパッケージをインストールする次に、オペレーティングシステム内のすべてのサービス...

Linux Centos7 に mysql8 をインストールするチュートリアル

1. RPMバージョンのインストールデータベースの他のバージョンがあるかどうかを確認し、ある場合は完...

HTTPS の有効化に関する経験の共有

国内のネットワーク環境が悪化し続ける中、さまざまな改ざんや乗っ取りが後を絶たず、サイト全体をHTTP...

Dockerでデータディレクトリを移行する方法

目次ディスク使用量の表示ディスク クリーンアップ (軽々しく使用しないでください)データの移行ディス...

MySQL コマンドライン操作中のエンコードの問題の詳細な説明

1. MySQLデータベースのエンコーディングを確認する mysql -u ユーザー名 -p パスワ...

MySQL データベースの詳細な説明 (Ubuntu 14.0.4 LTS 64 ビットベース)

1. MySQLデータベースの構成と関連概念まず、MySQL はリレーショナル データベースである...

Ubuntu 16.04.5LTS に SVN をインストールする手順

この記事では、UbuntuシステムでSVNを設定するプロセスを簡単に紹介します。ソースを更新sudo...

HTML ページ共通スタイル (推奨)

以下のように表示されます。 XML/HTML コードコンテンツをクリップボードにコピーbody、di...

MySQLの高可用性アーキテクチャの詳細な説明

目次導入MySQL 高可用性マスター 1 つとバックアップ 1 つ: MySQL マスター スレーブ...

Windows と Linux 間のリモート デスクトップ接続

Linux へのリモート デスクトップ接続といえば、まず VNC の使用を思い浮かべるかもしれません...

Angular CDK を使用してサービスポップアップトーストコンポーネント機能を実装する

目次1. 環境設備2. ToastコンポーネントとToastServiceを作成する2.1 Toas...

Vue のトランジション効果とアニメーショントランジションの使用例の詳細な説明

目次遷移フック関数カスタム遷移クラス名遷移グループの使用まとめまずは例を見てみましょうコードは次のと...

Angularが予期しない例外エラーを処理する方法の詳細な説明

前面に書かれたコードがどれだけ適切に記述されていても、すべての可能性のある例外を完全に処理することは...

JavaScript の条件付きアクセス属性と矢印関数の紹介

目次1. 条件付きアクセス属性2. アロー関数の紹介1. 条件付きアクセス属性?. は ES2020...