[基本タイプスクリプト入門-基礎から実戦へ]-ジェニーリック


この文章はタイプスクリプト入門-ベースから実戦へのジェニーリックを見て整理したものだ.

紹介する


ジェニーリックは、関数のパラメータのようにタイプを使用することを意味します.
ジェニーンリック|タイプスクリプトマニュアル

ジェニーリックの基本文法

// 일반 함수형
function logText<T>(text: T): T {
    console.log(text);
    return text;
}

// 화살표 문법
const logText = <T>(text: T): T => {
  console.log(text);
  return text;
}; // tsx에선 <T extends unknown>와 같이 extends를 붙여주어야 한다고 함

logText('하이'); // 1
logText<string>('하이'); // 2
関数でJENICを使用するには、次のように記述して使用します.logText('하이')という名前の関数を呼び出すと、関数は内部からタイプを推定し、文字列タイプを識別して起動します.logText<string>('하이')は、文字列タイプをJENICに変換し、vscodeからタイプが何であるかを直接見ることができるようにJENICを使用して直接呼び出されます.

従来のタイプ定義方法とJennikの違い-関数の繰り返し宣言の欠点

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

function logNumber(num: number) {
  console.log(num);
  return num;
}

logText('a');
logText(10);
logNumber(10);
logText(true);
既存のタイプ定義で関数を定義すると、タイプに応じて異なる関数が作成されるのでconsole.logセクションとreturn文が重複していることを確認できます.

従来の構文とGenericの違い-Unionタイプの宣言を使用して問題が発生

function logText(text: string | number) {
  console.log(text);
  return text;
}
logText('a');
logText(10);
入力のタイプ化は可能であるが,vscodeは関数内のパラメータ法からstringとnumber交差を用いる方法を推奨する.
また,返却値を受け取った後もstring|number型であるため,ここでは交差する方法も推奨する.


ジェニーリックの長所とタイプ推定のメリット

function logText<T>(text: T): T {
  console.log(text);
  return text;
}

const str = logText<string>('abc');
str.split('');
const login = logText<boolean>(true);
先ほどJENICを使っていない関数で見た問題は、JENICを使えば解決できます.(戻り値と関数のタイプは一体)
JENIC呼び出しでタイプを定義!

ジェニーン・レイクの実戦例-例の説明


これは一例なので、脈絡の説明は省略します-->詳しくは授業中です.

Generic実戦例-コードでタイプを定義

const emails = [
  { value: 'naver.com', selected: true },
  { value: 'gmail.com', selected: false },
  { value: 'hanmail.net', selected: false },
];

const numberOfProducts = [
  { value: 1, selected: true },
  { value: 2, selected: false },
  { value: 3, selected: false },
];

function createDropdownItem(item) {
  const option = document.createElement('option');
  option.value = item.value.toString();
  option.innerText = item.value.toString();
  option.selected = item.selected;
  return option;
}

// NOTE: 이메일 드롭 다운 아이템 추가
emails.forEach(function (email) {
  const item = createDropdownItem(email);
  const selectTag = document.querySelector('#email-dropdown');
  selectTag.appendChild(item);
});
初めてコードを見たとき、普通のJS文法のように何か書いていませんでした.これをts構文に変換すると、次のようになります.
interface Email {
  value: string;
  selected: boolean;
}

const emails: Email[] = [
  { value: 'naver.com', selected: true },
  { value: 'gmail.com', selected: false },
  { value: 'hanmail.net', selected: false },
];

interface ProductNumber {
  value: number;
  selected: boolean;
}

const numberOfProducts: ProductNumber[] = [
  { value: 1, selected: true },
  { value: 2, selected: false },
  { value: 3, selected: false },
];

function createDropdownItem(item: ProductNumber) {
  const option = document.createElement('option');
  option.value = item.value.toString();
  option.innerText = item.value.toString();
  option.selected = item.selected;
  return option;
}

// NOTE: 이메일 드롭 다운 아이템 추가
emails.forEach(function (email) {
  const item = createDropdownItem(email); // 에러 발생
  const selectTag = document.querySelector('#email-dropdown');
  selectTag.appendChild(item);
});
こう書くと、createDropdownItemの買収項目がEmailの場合もあれば、ProductNumberの場合もあるので、エラーが発生します.
-->Unionタイプに置き換え
...

function createDropdownItem(item: Email | ProductNumber) {
  ...
問題は解決したようですが、item値に新しい値が含まれるたびに、インタフェースを定義し、Unionタイプで記述する必要があります.これは拡張性に合致しません-->インターフェイスJENERICを使用!

インタフェースでJENICを宣言する方法

// 인터페이스에 제네릭을 선언하는 방법
interface Dropdown<T> {
  value: T;
  selected: boolean;
}
const obj: Dropdown<string> = { value: 'abc', selected: false };
インタフェースでJENICを使用するために、<T>パラメータが受け入れられ、valueに割り当てられる.また、使用する場合は、タイプファクタを出せばよい.

ジェニーリックの実戦例-ジェニーリック定義タイプを使用

interface DropdownItem<T> {
  value: T;
  selected: boolean;
}

// interface Email {
//   value: string;
//   selected: boolean;
// }

const emails: DropdownItem<string>[] = [
  { value: 'naver.com', selected: true },
  { value: 'gmail.com', selected: false },
  { value: 'hanmail.net', selected: false },
];

// interface ProductNumber {
//   value: number;
//   selected: boolean;
// }

const numberOfProducts: DropdownItem<number>[] = [
  { value: 1, selected: true },
  { value: 2, selected: false },
  { value: 3, selected: false },
];

function createDropdownItem(item: DropdownItem<string> | DropdownItem<number>) {
  const option = document.createElement('option');
  option.value = item.value.toString();
  option.innerText = item.value.toString();
  option.selected = item.selected;
  return option;
}

// NOTE: 이메일 드롭 다운 아이템 추가
emails.forEach(function (email) {
  const item = createDropdownItem(email);
  const selectTag = document.querySelector('#email-dropdown');
  selectTag.appendChild(item);
});
先ほど作成したEmailProductNumberのインタフェースを外し、DropdownItemのインタフェースにGenericを使用して作成すれば、上記のコードのように作成できます.
Unionタイプを除いて、createDropdownItemを定義すると、以下のように記述できます.
// 정의
function createDropdownItem<T>(item: DropdownItem<T>) 

// 호출 시
createDropdownItem<string>(email)
createDropdownItem<number>(product)

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

// 제네릭의 타입 제한
function logTextLength<T>(text: T): T {
  console.log(text.length);
  return text;
}

logTextLength<string>(['hi', 'abc']);
上のコードでは、次のエラーが表示されます.

これは、logTextLengthという現在定義されている買収にタイプスクリプトがどのようなタイプを導入するか分からないためです.
そのため、ジェニーンリックT []アレイアンテナを与えれば、問題は解決される.
// 제네릭의 타입 제한
function logTextLength<T>(text: T[]): T[] {
  console.log(text.length);
  text.forEach(text => {
    console.log(text);
  });
  return text;
}

logTextLength<string>(['hi', 'abc']);
したがって、タイプ制限はジェニーリックに追加のタイプヒントを与える方法です.

定義されたタイプ制限タイプの使用

// 제네릭 타입 제한 2 - 정의된 타입 이용하기
interface LengthType {
  length: number;
}

function logTextLength<T extends LengthType>(text: T): T {
  text.length;
  return text;
}
logTextLength('a');
logTextLength({length: 10});
logTextLength(10); // 에러 발생
定義されたインタフェース、例えばextendsキーワードを使用して、定義JENICはタイプを制限することができる.
文字列aの場合、lengthというpropertyがあり、オブジェクトに渡されるのもlengthというpropertyがあるが、数字10にlength propertyがないためエラーが発生する.

制限keyofロジャーネリックのタイプ

// 제네릭의 타입 제한 3 - keyof
interface ShoppingItem {
  name: string;
  price: number;
  stock: number;
}

function getShoppingItemOption<T extends keyof ShoppingItem>(itemOption: T): T {
  return itemOption;
}

// getShoppingItemOption(10);
// getShoppingItemOption<string>('a');
getShoppingItemOption('name');
jenericに到達できるパラメータとしてkeyofという名前の保持語を使用して、インタフェースで定義された属性(キー値のみ)のみを許可できます.