본문 바로가기
개인공부/캡틴판교 TS

10. 제네릭

by 뭉지야 2023. 5. 7.
728x90

제네릭(Generics)
- c#, java 등의 언어에서 재사용성이 높은 컴포넌트를 만들때 자주 활용되는 특징이다.

 

<제네릭 기본문법>

// function logText(text){
//     console.log(text);
//     return text;
// }
// logText(10); //숫자10
// logText('하이')  // 문자열 하이
// logText(true);  // 진위값 true

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

logText<string>('하이');

 

< 기존 타입 정의 방식과 제네릭의 차이점 - 함수 중복 선언의 단점 >

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

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

logText('a');
logNumber(10);

 

< 기존 타입 정의 방식과 제네릭의 차이점 - 유니온 타입 방식의 문제점 >

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

const a = logText('a');
a.split('');  
//입력값은 해결되었지만, 반환값에서 오류가 난다.
// number는 split이 안된다.
logText(10);

 

< 제네릭의 장점과 타입 추론에서의 이점 >

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

const str = logText<string>('abc')
str.split('');

const login = logText<boolean>(true);

 

< 제네릭 실전 예제 살펴보기 - 코드에 타입 정의하기 >

//기존 코드


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);
});
// 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: Email | 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);
});

 

< 인터페이스에 제네릭을 선언하는 방법 >

interface Dropdown {
    value: string;
    selected: boolean;
}

const obj: Dropdown = { value: 'abc', selected: false };
// 인터페이스에 제네릭을 선언하는 방법

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

const obj: Dropdown<string> = { value: 'abc', selected: false };

 

< 제네릭 실전 예제 살펴보기 - 제네릭을 이용한 타입 정의 >

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

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


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

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

// interface TrueFalse {
//   value: boolean;
//   selected: boolean;
// }

const numberOfProducts: DropdownItem<number>[] = [
// const numberOfProducts: ProductNumber[] = [
  { 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);
});

 

< 제네릭의 타입 제한 >

// 제네릭의 타입 제한
function logTextLength<T>(text: T[]): T[] {
    console.log(text.length);
    text.forEach(function (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(10);   //에러
logTextLength({ length: 10 });

 

< keyof로 제네릭의 타입 제한하기 >

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

//ShoppingItem중의 한가지가 T가 된다는 의미이다.
function getShoppingItemOption<T extends keyof ShoppingItem>(itemOption: T): T {
    return itemOption;
}

getShoppingItemOption('name');

T extends keyof ShoppingItem     : shoppingItem중의 한가지가 T가 된다는 의미이다!!!

 

 

728x90

'개인공부 > 캡틴판교 TS' 카테고리의 다른 글

11. 실습(전화번호부)  (0) 2023.05.07
9. 클래스  (0) 2023.05.07
7. 유니언타입, 인터섹션타입  (0) 2023.05.07
6. 타입별칭, 타입과 인터페이스차이  (1) 2023.05.07
5. 인터페이스  (0) 2023.05.07