TL;DR: TypeScript ジェネリックを使用すると、開発者は型の安全性を維持しながらさまざまなデータ型を処理できる再利用可能なコードを作成できます。これらは、堅牢でスケーラブルな TypeScript アプリを構築するために不可欠です。
コードの透明性と管理性を確保するために、Typescript では数種類のデータを安全かつ効果的に管理する必要があります。 Typescript の中核機能の 1 つは Typescript ジェネリックスです。これにより、厳格な型制限を遵守しながら関数、クラス、インターフェイスを作成できます。ジェネリックを使用すると、作成するコードの量が減り、間違いが少なくなり、そして最も重要なことに、さまざまなデータ型に対応した柔軟なコンポーネントを構築できます。
この記事では、関数、クラス、インターフェイスでの使用法など、タイプスクリプト ジェネリックスの本質を探り、コードをどのように多用途かつ堅牢にするかを示します。
Typescript ジェネリックは、プレースホルダー型を使用して Typescript コードを定義できるため、タイプセーフを維持しながら、柔軟性、拡張性、再利用可能にすることができます。
Typescript は、ジェネリック型を定義するプレースホルダーとしてコンパイル時に型の安全性チェックを行います。コンポーネントが実装されると、プレースホルダーは実際の型に置き換えられます。この手法を使用すると、データ型ごとに個別の実装を必要としないため、重複性の管理と削減が容易になります。
ジェネリックを使用しないと、異なるデータ型を処理するために複数のバージョンの関数またはクラスを作成することになり、コードの重複が発生します。ジェネリックを使用すると、静的な型チェックを維持しながら、さまざまな種類に再利用可能な単一の実装が可能になります。
次のセクションのコード例は、この違いを理解するのに役立ちます。
ジェネリックを typescript のさまざまな部分で使用すると、型をより効率的に管理できます。これらは、柔軟性が重要な関数、インターフェイス、クラス、その他の構造に役立ちます。
ジェネリックは、冗長性を減らすために関数に適用されることがよくあります。たとえば、文字列または数値をパラメータとして受け取る関数について考えてみましょう。
function identity(value: any): any { return value; } const result1 = identity(42); // result1: any const result2 = identity("hello"); // result2: any
この機能は正常に動作します。ただし、任意の型を使用するため、Typescript は特定の型を追跡できなくなります。その結果、戻り値の型は any, となり、Typescript はタイプ セーフを強制できなくなります。型の安全性を維持する必要がある場合は、2 つの異なる関数を作成する必要があります。1 つは文字列を返し、もう 1 つは数値を返します。ただし、このアプローチではコードの重複が増加します。
ジェネリックを使用して型情報を保存することで、上記の関数を改善できます。
function identity(value: any): any { return value; } const result1 = identity(42); // result1: any const result2 = identity("hello"); // result2: any
T は、この場合メソッドが使用する型を表します。存在する場合、Typescript は入力の型と戻りパラメーターの型が同じであることを確認します。
また、パラメータの型を明示的に定義せずに関数を定義することもできます。
function identity<T>(value: Type): T { return value; } const result1 = identity<number>(42); // result1: number const result2 = identity<string>("hello"); // result2: string
Typescript では、単一の関数またはコンポーネントで複数の型を操作するときに、複数のジェネリック型パラメーターを使用できます。たとえば、2 つの異なるタイプの入力を受け取り、それらをペアとして返す関数が必要になる場合があります。
const result3 = identity(100); // result3: number const result4 = identity("world"); // result4: string
この場合、関数は型 T の最初の要素と型 U の 2 番目の要素を持つタプルを返します。これにより、関数による 2 つの異なる型の型安全な処理が可能になります。
Typescript では、ジェネリックにデフォルトの型を提供して、それをオプションにすることができます。タイプが指定されていない場合、Typescript はデフォルトを使用します。
function multipleParams<T, U>(first: T, second: U): [T, U] { return [first, second]; } const result1 = multipleParams<string, number>("hello", 42); // result1: [string, number] const result2 = multipleParams<string, number>("hello", "world"); // result2: gives a type error
この例では、型パラメータ T のデフォルトは文字列です。開発者が関数を呼び出すときに特定の型を指定しない場合、T はデフォルトで文字列になります。
Typescript ジェネリックスはインターフェイスにも適用できます。 任意の タイプの値を持つ Box インターフェースを定義するとします。
function createArray<T = string>(length: number, value: T): T[] { return Array(length).fill(value); } const stringArray = createArray(3, "hello"); // T defaults to string, so stringArray is a string array const numberArray = createArray<number>(3, 42); // T is explicitly set to a number, so numberArray is a number array
これは一般的な関数の例とより同等です。特定の型を定義していないため、このコードも問題なく動作します。ただし、値は any, として型付けされるため、型関連のバグが発生する可能性があります。
型を保護するために、ここで汎用インターフェイスを定義できます。
interface Box { value: any; } const numberBox: Box = { value: 123 }; // correct const stringBox: Box = { value: "hello" }; // correct
インターフェイスは汎用であり、その値の型は Type 変数に厳密に制限されます。 Type 変数は、インスタンスの作成時に数値または文字列として指定できるため、Typescript は適切な型が遵守されるようになります。
クラスは、型の安全性を維持しながらさまざまな型を処理するジェネリックスを使用して作成することもできます。 任意の型の値を格納および取得できるStorageクラスを作成しましょう。
interface Box<Type> { value: Type; } const numberBox: Box<number> = { value: 123 }; // number const stringBox: Box<string> = { value: "hello" }; // string const stringBox2: Box<string> = { value: 123 }; // incorrect
このクラスは機能しますが、データの型が any, であるため、getItem メソッドは any, を返し、タイプ セーフティが削除されます。したがって、ジェネリックスを使用してクラスを書き直して、型安全性を向上させることができます。
class Storage { private data: any; setItem(item: any): void { this.data = item; } getItem(): any { return this.data; } } const storage = new Storage(); storage.setItem(123); const item = storage.getItem();
この場合、タイプ T は Storage クラスによって使用されます。 Typescript は、インスタンスの作成時にデータの型を定義するときに、データが正しいことを保証します。このコード例の getItem メソッドは数値を生成します。
ジェネリック制約を使用すると、ジェネリックが受け入れることができる型を制限し、ジェネリックが特定のプロパティを持つようにすることができます。
たとえば、入力の length プロパティにアクセスする必要がある関数がある場合、制約を使用して、length プロパティを持つ型のみが許可されるようにすることができます。 。これにより、Typescript でエラーが発生したり、互換性のない型がすり抜けたりすることがなくなります。
function identity(value: any): any { return value; } const result1 = identity(42); // result1: any const result2 = identity("hello"); // result2: any
ここでは、値 T は length プロパティで定義されていません。この問題を無視するには、T に length プロパティが必要であることを指定する制約を追加します。これを行うには、T extends { length:number }.
とします。
function identity<T>(value: Type): T { return value; } const result1 = identity<number>(42); // result1: number const result2 = identity<string>("hello"); // result2: string
この関数には length プロパティが含まれます。エラーは発生せず、入力の長さで実行されます。
Typescript ジェネリックを使用すると、柔軟性があり、再利用可能で、タイプセーフなコードを作成できます。これらのジェネリックを持つクラス、メソッド、インターフェイスを使用すると、コードを繰り返さずに多くのデータ型を管理できます。汎用制約、多数の型、およびデフォルトの型は、この投稿で取り上げた主要な使用例の一部であり、それぞれがプログラムのスケーラビリティと保守性をどのように向上させることができるかを示しました。
Typescript ジェネリックスを理解すると、より正確で、適応性があり、タイプセーフなコードを作成し、Typescript アプリケーションをより堅牢にすることができます。
以上がTypeScript ジェネリック: 完全ガイドの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。