Generics


Generics


1つのタイプと比較して、複数のタイプ(Multiple Type)の構成部品を使用して、モーション構成部品を作成および再使用できます.

基本構文


ジェニーリックは、関数を伝達する引数のようにタイプを使用します.
// main.ts
function func <T>(param: T): T {
    return param;
}

func<type>(param);
func関数では、<T>は、関数を呼び出すときに渡されるタイプです.
関数を呼び出すと、呼び出し文に<type>を作成し、関数定義で作成されたJENICタイプにタイプを渡して、関数内部で渡されるタイプを使用できます.
// main.ts
function logText(text) {
    console.log(text);
    return text;
}

logText('hi');
logText(10);
logText(true);
上記のコードでは、logText関数はパラメータとして任意のタイプの値を渡すこともできるし、任意のタイプの値を返すこともできる.これは、パラメータと戻り値のタイプをanyとして指定するのと同じです.
Genericを使用して、次の内容を作成できます.関数を呼び出すと、関数名とカッコの間に<type>を作成し、関数のネストされたタイプにタイプを渡すことができます.関数は、渡されたタイプを使用してパラメータまたは戻り値のタイプを指定できます.
// main.ts
function logText<T>(text: T): T {
    console.log(text);
    return text;
}

logText();
この関数を定義し、logText関数呼び出し文にカーソルを合わせると、次のプレビューが表示されます.

これは、関数を呼び出すときにパラメータと戻り値のタイプを決定することを意味します.文カッコを呼び出す前に<string>を作成し、文字列タイプを呼び出し関数に渡すと、テキストパラメータとlogText関数の戻り値は文字列タイプによって決まります.

つまり、関数を呼び出すときに、関数で定義されたJENICタイプを引数とともに渡し、関数で渡すタイプを利用できるようにします.

ジェニーリックの長所


1.関数繰り返し宣言

// main.ts
function logText(text: string) {
    console.log(text);
    return text;
}

logText('string');
logText(100); // -> X, stirng 타입의 값만 전달 가능
logText(true):  // -> X, stirng 타입의 값만 전달 가능
logText関数のパラメータはstringタイプとして定義されているため、関数を呼び出すときに渡すパラメータのタイプもstringタイプでなければなりません.複数のタイプの値を引数として渡す場合は、各パラメータタイプに関数を指定する必要があります.
// main.ts
function logText(text: string) {  // -> sting 타입
    console.log(text);
    return text;
}

function logNum(num: number) {  // -> number 타입
    console.log(num);
    return num;
}

function logBoolean(text: boolean) {  // -> boolean 타입
    console.log(text);
    return text;
}

logText('string');
logNum(100);
logBoolean(true);
メンテナンスの面では、複数のタイプを使用するために冗長コードを生成するだけでは望ましくない.
Unionタイプを使用して、この問題を解決できます.

2.Unionタイプの問題

// main.ts
// 인수로 string or number or boolean 타입의 값을 전달 받음
fucntion logText(text: string | number | boolean) {
    console.log(text);
    return text;
}

logText('string');
logText(100);
logText(true);
上記の重複コード生成の問題は解決されましたが、Unionタイプでは以下の問題があります.
fucntion logText(text: string | number | boolean) {
    console.log(text);
    return text;
}

const str = logText('string');
文字列「string」をlogText関数に渡すと、文字列値はstr変数に割り当てられます.ここではstr変数のタイプをstringタイプとして指定すると予想されるが、実際にはstr変数は「string | number | booleanのunionタイプ」として指定されている.

これはStringタイプの値の変数です.下図に示しますが、Stringです.Prototypeのメソッドは使用できません.

このプロパティを使用するには、どのタイプの値が正確に入力されているかを知る必要があるため、エラーを示します.numberはsplitをサポートしていません.タイプスクリプトを使用する理由の1つは、コードの生産性が向上しないためです.
すなわち,パラメータのタイプの問題が解決されると,戻り値の問題は依然として解決されない.

ジェニーリックの長所


JENERICを使用すると、Unionタイプで値を返す問題も解決できます.
// main.ts
// <T>라는 제네릭 타입 작성
function logText <T>(text: T): T {
    console.log(text);
    return text;
}

logText<string>('string');  // -> string 타입을 제네릭 타입에 전달
上記のコードで関数を定義する場合、関数名の横に<T>を作成し、パラメータと関数の戻り値の各タイプをTと指定します.
関数を呼び出すときに関数名の横に<string>を作成することにより、TをJENERICタイプのstringに渡す.関数が呼び出されると、入力されたstringによってパラメータと戻り値のタイプが指定されます.

stringに加えてnumberとbooleanは、呼び出し時にパラメータと戻り値のタイプを動的に決定するために、呼び出し時に渡すことができます.


すなわち、関数を定義するときに、タイプを空にし、関数を呼び出すときに動的にタイプを指定することができます.

従来のUnionタイプとは異なり、str変数はstringタイプとして認識され、stringが関連付けられる.prototypeプロパティが自動完了として表示されます.

インタフェースでジェニーリックを宣言する方法


インタフェース定義を作成するときに、JENICタイプを作成して、インタフェースを使用するときにインタフェース内で使用できるようにタイプを渡すこともできます.
// main.ts
interface Fruit {
    name: string;
    stock: string;
}

cosnt apple: Fruit = { name: 'apple', stock: 'restock' };

interface Shoes {
    name: string;
    stock: boolean;
}

const nike: Shoes = { name: 'nike', stock: false };
上記のコードに示すように、異なるタイプのシードインタフェースとシードインタフェースをそれぞれ定義する必要があります.
これらのインタフェースでは、JENICを介してインタフェースを使用するときにJENICを介して渡されるタイプを作成して、タイプを動的に指定することもできます.
// main.ts
interface stock<T> {  // -> 제네릭 타입 <T>를 작성
    name: string;
    stock: T;
}

// 제네릭 타입에 string 타입 전달
const apple: Stock<string> = { name: 'apple', stock: 'restock' };

// 제네릭 타입에 boolean 타입 전달
const nike: Stock<boolean> = { name: 'nike', stock: false };
上記コードに示すように、Stockインタフェースを使用する場合、Stockの隣に<string>を作成し、TをJennicタイプのstringに渡し、stockにstringタイプを持たせる.<boolean>をJennicタイプのTに渡し、stockにbooleanタイプを持たせる.
つまり、「1つのインタフェースでJENICを使用して複数のタイプの役割を果たす」ことで、タイプコードを減らすことができます.

ジェニーリックのタイプ制限

// main.ts
function logTextLength <T>(text: T): T {
    console.log(text.length);
    return text;
}

logTextLength<string>('string');
上のコードでlogTextLength関数にtextを入力します.lengthセクションにエラーが表示されます.これは、タイプスクリプトがパラメータが渡す値が分からないため、textというパラメータがlength propertyがあるかどうか分からないことを示します.

Genericタイプのbooleanキーワードを使用して、タイプスクリプトが存在するPropertyを明示的に伝えることができます.
// main.ts
interface LengthType {
    length: number;
}

// 제네릭 타입인 T는 상위 타입으로 LengthType을 가진다
// 즉, T는 반드시 length 프로퍼티를 갖는다
function logTextLength <T extends LengthType>(text: T): T {
    console.log(text.length);
    return text;
}

logTextLength<string>('string');
既存のJENERICタイプextends<T>と書くと、JENERICタイプは常にLenghTypeのサブタイプであり、LenghTypeが提供する製品が存在しなければならないことを明確に示す.

logTextLength関数の引数を使用して数値タイプの値を渡すと、エラーが発生します.

これは、数値タイプにlengthプロパティが存在しないため、エラーが表示されます.
すなわち,引数は長さプロファイルが存在する値のみを伝達する.