TypeScript ジェネリックを簡単に説明する方法

TypeScript ジェネリックを簡単に説明する方法

概要

TypeScript では、ジェネリックを使用して関連する関数の型を制限します。ここでの関数にはクラスのコンストラクターも含まれるため、クラスの宣言部分でもジェネリックを使用できます。では、ジェネリック医薬品とは一体何でしょうか?ジェネリックをシンプルに理解したらどうなるでしょうか?

ジェネリック医薬品とは

ジェネリックとは、関数、インターフェース、またはクラスを定義するときに特定の型を事前に指定せず、使用時に型を指定する機能を指します。

簡単に言えば、ジェネリックは型システムにおける「パラメータ」であり、その主な機能は型を再利用することです。上記の定義からわかるように、関数、インターフェース、クラスでのみ使用されます。これは js プログラム内の関数パラメータとは異なります (意味は同じですが)。Typescript は静的型システムであり、js がコンパイルされるときに型チェックを実行するシステムであるためです。そのため、ジェネリック パラメータは実際にはコンパイル プロセスの実行時に使用されます。関数パラメータとまったく同じ特性を持つため、「パラメータ」と呼ばれます。

関数increse(パラメータ) {
  // ...
}

型システムでは、ジェネリックを次のように使用します。

関数増加<T>(パラメータ: T): T {
  //...
}

param が型の場合、T はこの型に割り当てられ、戻り値では、型チェックのために T はこの型になります。

ビルドシステム

Typescript の型システム自体もプログラミングが必要であることはご存知でしょうが、そのプログラミング方法は奇妙です。プログラム コードに js コードを散りばめる必要があります (ts コードに js コードを散りばめるという言い方は奇妙です。なぜなら、直感的には ts コードが js コードに混ざっていると感じられるからです)。

プログラミングにおいて、最も重要な形式の 1 つは関数です。 Typescript の型プログラミングで、関数を見たことがありますか?いいえ。これは、ジェネリックがあるところには関数がありますが、関数の形式は js コードによって分割されるためです。最終製品を取得するには、Typescript をコンパイルする必要があります。コンパイルプロセス中に行うべきことは 2 つあります。1 つは、メモリ内で型プログラミング コードを実行して、型チェック システムを形成することです。つまり、js コードの型チェックを行うことができます。まず、typescript コンパイラは、ts プログラミング コードを実行した後、ランタイム チェック システムを取得します。この記事は Fei Zige のポッドキャストからのもので、このシステムを実行して、そこに散在する js コードに対して型アサーションを実行します。2 つ目は、js を出力することです。出力プロセス中、コンパイル システムは型プログラミング コードを実行しました。php コードで echo js コードを実行するのと同じように、php コードが実行され、表示されるのは js コードです。

この観点から TypeScript を見ると、なぜそれが JavaScript のスーパーセットと呼ばれ、コンパイルされた結果が JS になるのかをよりよく理解できるかもしれません。

ジェネリック医薬品の一般的な理解

TS コンパイル システムのロジックを理解したので、型プログラミングと JS 自体のビジネス プログラミングを感情的に区別できるようになりました。ここで言及している「ジェネリック」は、ts のコンパイルされたランタイム コードである型プログラミング部分にのみ存在します。

簡単な例を見てみましょう:

関数増加<T>(パラメータ: T): T {
  //...
}

このコードから js コードを分離し、型の説明テキストを使用してそれを表すとどうなるでしょうか?

//関数@typeを宣言し、パラメータはT、戻り値は(T): T 
@type = T => (T): T

// 関数を実行して、型 (number): number の型 F を取得します。
@F = @type(数値)

// 増加関数は F 型に準拠する必要があります。つまり、パラメータは数値で、戻り値も数値です。 
@@F
関数増加(パラメータ) { 
  // ... 
} 
@@終わり

実際には @@F のような構文はありません。型システムを別の観点から見ることができるように作成しました。

ジェネリックが一種の「パラメーター」であると理解したら、型システムの機能はどこにあるかという疑問が湧くかもしれません。 js 関数の場合は関数宣言文とパラメータを簡単に指摘できますが、ts ではこの部分は隠されています。ただし、特定の構造では型関数の影が簡単に確認できます。

// ジェネリックインターフェースを宣言します。これは関数を宣言するのと同じように記述します。記述には記述言語を使用します。@type = T => (T): T
インターフェース GenericIdentityFn<T> {
    (引数: T): T;
}

// この書き方はクロージャ関数に少し似ています。関数を宣言すると、すぐに実行されます。記述言語: @@[T => (T): T](any)
関数アイデンティティ<T>(引数: T): T {
    引数を返します。
}

// ジェネリックインターフェースの使用は関数の呼び出しに似ています。記述言語を使用して@type(number)を記述します。
myIdentity: GenericIdentityFn<number> = identity; とします。

上記のコード全体を説明テキストを使用して書き直してみましょう。

@GenericIdentityFn = T => (T): T

@@[T => (T): T](任意)
関数識別(引数) {
  戻り引数
}
@@終わり

@@GenericIdentityFn(数値)
myIdentity = identityとする
@@終わり

型システムで、@GenericIdentityFn と @some (匿名関数 @[T => (T): T]) の 2 つの関数を宣言します。これらは 2 つの関数ですが、実際にはまったく同じです。これは、TypeScript が構造型であるためです。つまり、型をチェックするときに、型変数自体のポインターを同じに保つ必要はなく、構造内の各ノードの型が同じかどうかのみを判別します。 @GenericIdentityFn と @some は、それぞれ identify と myIdentify を変更するために呼び出されます。呼び出し時に異なるパラメータを受け取るため、最終的な型チェック ルールが異なります。Identify では、パラメータと戻り値の型が同じであることだけを確認する必要があります。具体的な型については、any が使用されます。 myIdentify では、パラメータの戻り値の型が同じであることを確認するだけでなく、型が数値であることも要求します。

ジェネリッククラス

ジェネリック インターフェイスに加えて、クラス クラスもジェネリック化できます。つまり、「ジェネリック クラス」です。ジェネリック クラスの助けを借りて、ジェネリックを宣言して使用する手順を調べてみましょう。

クラス GenericNumber<T> {
    ゼロ値: T;
    追加: (x: T, y: T) => T;
}

myGenericNumber = new GenericNumber<number>() とします。

前回の記事のジェネリックインターフェースは関数の型を制約するためだけに使用されているため、関数のように記述されています。実際には、ジェネリックインターフェースとジェネリッククラスは記述言語を使用して再記述できます。上記の赤い部分を説明するために、説明的な言語を使用します。

@GenericNumber = T => クラス {
  ゼロ値: T;
  追加: (x: T, y: T) => T;
}

@GenericNumber 関数は T をパラメータとして受け取り、クラスを返します。パラメータ T は @type 関数本体で複数回使用されます。

@GenericIdentityFn = T => インターフェース { 
  (引数: T): T; 
}

以前のインターフェース GenericIdentityFn を再記述して、インターフェースに他のメソッドを追加できるようにします。

Array などの TypeScript の組み込み基本型がジェネリック インターフェイスおよびジェネリック クラスとして宣言された後でも、これらのインターフェイスおよびクラスは、使用時に <> を介してパラメータを渡す必要があることがわかります。本質的には、これらはすべて関数であるため、戻り値が異なるだけです。

ジェネリックの使用に関するその他の一般的な説明

次に複合型を記述する必要があります。

クラス動物{
    numLegs: 数値;
}

関数createInstance<A extends Animal>(c: new () => A): A {
    新しいc()を返します。
}

今は new() の部分を見るのではなく、山括弧内の extends 構文を見てみましょう。どのように理解すればよいでしょうか?実際、私たちが直面する疑問は、コンパイル時に、<A extends Animal> の山括弧内のコンテンツがいつ実行されるのか、それらの前かその間かということです。

// @type = (A extends Animal) => (new() => A): A
@type(T)
// それでも @type = A => (new() => A): A
@type(T は Animal を拡張します)

TypeScript は静的型システムであり、Animal は不変クラスであるため、山括弧の内容はクラスが作成される前に実行されていると推測できます。

@type = (A は Animal を拡張します) => (new() => A): A

つまり、@type(T) を使用して型を生成するには、まず T が Animal の構造を満たしている必要があり、その後、必要な型を取得できます。T が Animal クラスの構造を満たさなくなった場合、コンパイラは直接エラーを報告します。このエラーは、型チェックの段階ではなく、型システムの作成段階、つまり ts コードの実行段階で発生します。この状況は「一般的な制約」と呼ばれます。

さらに、<A,B> のような構文は、実際には関数パラメータと同じです。

@type = (A, B) => (A|B): 何らかの型

tsの組み込み基本型を見てみましょう: Array<number>

@配列 = 任意 => 任意[]

結論

Typescript のジェネリックは、実際には型生成関数のパラメーターです。この記事の内容はすべて架空のものであり、tsを理解する際にアイデアを展開するのにのみ適しています。実際のプログラミングには適していません。これをここに宣言します。

以上がTypeScriptジェネリックの詳しい説明です。TypeScriptジェネリックの詳細については、123WORDPRESS.COMの他の関連記事もご覧ください。

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

<<:  LinuxでのMySQLのインストール手順

>>:  spring-boot と docker-java に基づいて Docker コンテナの動的な管理と監視を実装します [完全なソース コードのダウンロード付き]

推薦する

Mysqlトランザクション処理の詳細な説明

1. MySQLのトランザクションの概念MySQL トランザクションは主に、操作量が多く複雑度の高い...

Mysqlチュートリアルでのグループランキングの実装例の詳細な説明

目次1. データソース2. データの総合順位1) 総合ランキング2) 同順位3) 同順位3. データ...

入力テキストボックスの入力実装プロパティを無効にする

今日は、開発でよく使われる、非常に便利な HTML タグをいくつかまとめてみたいと思います。これらの...

MySQL コマンドラインモードアクセス操作 MySQL データベース操作

使用環境cmd モードで、mysql --version と入力します (インストールされている M...

MySQL のロックに関する問題

ロックの分類:データ操作の粒度から:テーブルロック:操作時にテーブル全体がロックされます。行ロック:...

よく使われる Docker コマンドと例の概要と分析

目次1. コンテナライフサイクル管理(1)ドッカー実行(2)スタート/ストップ/リスタート(3)ドッ...

MySQL における 10 進数型の使用法の簡単な紹介

MySQL でサポートされている浮動小数点型は、 FLOAT 、 DOUBLE 、およびDECIMA...

Node の SMS API で検証コード ログインを実装するためのサンプル コード

1. ノードサーバーのセットアップ + データベース接続ここでの操作は比較的簡単でわかりやすいです。...

Linux システムで Java 環境変数を設定する方法

Java環境変数を設定するここで、環境変数は etc/profile に設定され、つまり、すべてのユ...

select @@session.tx_read_only が DB に大量に出現するのはなぜですか?

問題を見つける上位の SQL ステートメントを取得すると、DB が大量のselect @@sessi...

マークアップ言語 -

123WORDPRESS.COM HTML チュートリアル セクションに戻るには、ここをクリックして...

Windows 10 で MySQL の解凍バージョンをインストールする方法の詳細なグラフィック チュートリアル

MySQL のインストールは、インストール バージョンと解凍バージョンに分かれています。インストール...

JavaScript でカルーセル効果を実装する

この記事では、カルーセルの効果を実現するためのJavaScriptの具体的なコードを参考までに共有し...

ボタンをEnterキーに関連付けるjsコード

コードをコピーコードは次のとおりです。 <html> <ヘッド> <ス...

MySQLの比較演算子正規表現マッチングREGEXPの使用の詳細な説明

1. データを初期化する `test_01` が存在する場合はテーブルを削除します。 テーブル「te...