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を使用してすべての子要素を選択する方法の詳細な説明

推薦する

弾力性のあるナビゲーション効果を実現するJavaScript

この記事では、弾性ナビゲーション効果を実現するためのJavaScriptの具体的なコードを参考までに...

ページのスクロールバーを無効にするには、overflow: hiddenを使用します。

コードをコピーコードは次のとおりです。 html {オーバーフロー: 非表示; }体{オーバーフロー...

MacOS で Docker を使用して MySQL マスター スレーブ データベースを作成する方法

1. MySQLイメージを取得するターミナルから最新のMySQLイメージを取得するdocker pu...

シンプルなメッセージボードケースを実現するJavaScript

参考までに、Javascriptを使用してメッセージボードの例(メッセージ削除あり)を実装します。具...

MySQL テーブルをコピーする 3 つの方法 (要約)

テーブル構造とそのデータをコピーする次のステートメントは、データを新しいテーブルにコピーします。注:...

line-height=height要素の高さだがテキストが垂直方向に中央揃えされない問題を解決する

まず、行の高さが要素の高さと等しい場合にテキストが垂直方向に中央揃えにならない理由を説明します。実際...

SQL 実装 LeetCode (185. 部門内で最も給与の高い上位 3 名)

[LeetCode] 185. 部門別給与上位3位従業員テーブルにはすべての従業員が保持されます。...

LinuxにDockerをインストールする(非常に簡単なインストール方法)

最近、かなり暇です。大学4年生として数か月間インターンをしていました。インターンとして、Docker...

VMware および CentOS システムのインストール方法 - ルート パスワードをリセットする

今日のタスク1. Linuxディストリビューションの選択2.vmwareが仮想マシン(centos)...

Docker に MySQL と MariaDB をインストールする方法

MySQLとMariaDBの関係MariaDB データベース管理システムは MySQL のブランチで...

CSS と HTML とフロントエンド テクノロジーのレイヤー図

フロントエンドテクノロジー層 (写真は少し極端ですが、参考までに) Javascript と DOM...

過去の Linux イメージの問題を修正するためのサンプル分析

過去の Linux イメージに関する問題を修正従来の Linux イメージで作成された ECS クラ...

el-tree での不完全なテキスト表示の解決策

目次方法1: 水平スクロールバーを設定する最も簡単な方法方法2(新規):ドラッグバーを追加して外側の...

MySQL 5.7.18 のインストールと設定方法のグラフィックチュートリアル (CentOS7)

LinuxにMySQL 5.7.18をインストールする方法1. MySQLをダウンロードします。公...

Uniapp WeChatアプレット: キー障害の解決策

ユニアプリコード <テンプレート> <表示> <image v-for...