Generics : 제네릭

y0ung·2020년 11월 24일
0

TypeScript

목록 보기
7/12
post-thumbnail

🔹 제네릭의 사전적 의미


데이터 형식에 의존하지 않고, 하나의 값이 여러 다른 데이터 타입들을 가질수 있는 기술에 중점두어 재사용성을 높일수 있다.

제네릭 위키백과 참고

쉽게 말해서 제네릭이란 타입을 마치 함수의 파라미터처럼 사용하는 것 을 말한다.

예시

// JavaScript
function logoText(text){
  console.log(text);
  return text
}

logoText('hello') // 문자열 hello
logoText(20) // 숫자 20
logoText(true) // 불린값 true

위의 함수를 보면 text라는 파라미터에 값을 받아 text를 반환해 주는데 어떤 값이 들어가더라도 그대로 반환해준다.

제네릭을 사용한 함수

//TypeScript
function logoText<T>(text: T):T {
  console.log(text);
  return text
}

logoText('hello') // ①
logoText<string>('hello') // ②
  • <T>부분을 정해주지 않은경우 넘겨주는 파라미터를 반영해 준다.
  • <T>에 타입을 정의해줬을경우 해당 타입을 파라미터에 반영해 준다.

🔹 여러가지 타입 사용하기


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

타입을 다르게 받기 위해 중복선언을 하는 경우 유지보수 측면에서 효율적이지 못한 다는 단점이 있다.

function logoText(text:string){
  console.log(text);
  text.split('').reverse().join(' '); // 문자열이라 함수 사용이 가능하다.
  return text
}

function logoNumber(text: number) {
  console.log(text);
  return text
}
logoText('a') 
logoText(10) // error
logoNumber(10)

2. 기존 문법과 제네릭의 차이점 - 유니온 타입을 이용한 선언 방식의 문제점

함수의 중복선언을 쉽게 접근 하는 방식중 하나는 유니온 타입을 이용한 방식이다.

function logoText(text: string | number) {
  return text
}

const a = logoText('a');
a.split('') // error ①


  • 유니온을 사용했을 경우 정해준 타입에 맞는 인자를 전달해 줄수 있지만 api를 사용할수 없다.

    split은 문자열에 사용하는 api함수 인데 변수 a가 어떤타입인지에 대해서는 정해주지 않았기 때문에 오류가 난다.

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

같은함수에 제너릭을 이용하면 타입을 추론해 최종값을 반환해준다.

function logoText<T>(text:T):T {
  return text
}

const str = logoText<string>('abc');
const num = logoText<number>(10)
  • str
  • mum

제네릭을 활용한 예제

// 제네릭을 사용한 인터페이스
interface DropdownItem<T> {
  value:T;
  selected:boolean;
}

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

const numberOfProducts: DropdownItem<number>[] = [
  { value: 1, selected: true },
  //...
];

function createDropdownItem<T>(item: DropdownItem<T> ) {
  const option = document.createElement('option');
  //...
  return option;
}

// NOTE: 이메일 드롭 다운 아이템 추가
emails.forEach(function (email) {
  const item = createDropdownItem<string>(email);
  //...
});

🔹 제네릭의 타입 제한

function logoTextLength<T>(text: T): T {
  console.log(text.length); // Error: T doesn't have .length
  return text;
}

인자에 선언한 T는 아직 어떤 타입인지 정의해 주지 않았기 때문에 length에서 오류가 난다. 이럴때 해결하는 방법을 살펴보자.

1. 제네릭의 타입 제한

function logoTextLength<T>(text:T[]):T[]{
  console.log(text.length);
  return text
}

제네릭 타입이 배열 이기 때문에 length가 혀용된다.

2. 정의된 타입으로 타입을 제한하기

interface lengthType {
  length: number;
}

function logoTextLength<T extends lengthType>(text: T): T {
  console.log(text.length);
  return text;
}

logoTextLength(10) // error, 숫자는 length가 존재아지 않으므로
logoTextLength({length:0, value:'hi'}) // 동작

위와같이 작성하면 타입에 대한 강제는 아니지만 length에 동작하는 인자만 넘겨 받을수 있다.

3. keyof로 제한하기

interface SoppingItem{
  name:string;
  price:number;
  stock:number
}

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

getShoppingItemOption('name')

keyof속성을 사용하게 된다면 객체안에 있는 속성("name"|"price"|"stock")중 한가지만 받아 올수 있다.

ctr+space

getShoppingItemOption(ctr+space) 해당 함수에 ctr+space를 하게 되면 접근 가능한 인자속성을 알려준다.


참고

타입스크립트 핸드북
캡틴판교_타입스크립트 입문

profile
어제보다는 오늘 더 나은

0개의 댓글