65. Generics

조연정·2021년 1월 12일
0
post-thumbnail

C#, Java 등의 언어에서 재사용성이 높은 컴포넌트를 만들 때 자주 활용되는 '틀' 역할을 해주는 제네릭에 대해 알아보자.

Generics

타입스크립트에서 타입을 마치 함수의 파라미터처럼 사용하는 것을 의미한다.
제네릭을 사용하면 클래스나 함수의 목적 중 하나인 재사용성이 증가한다. 한가지 타입보다 여러가지 타입에서 동작하는 컴포넌트를 생성하는데 사용된다.

제네릭을 사용하는 이유

기존 타입 정의방식의 문제점이 무엇인지 파악하고, 비교해보면 제네릭이 왜 필요한지 쉽게 알 수 있다.

1.함수 중복 선언

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

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

logText('hi');
logNumber(10);

타입 종류에 따라 각각 다른 함수들을 만들어 주었다.
단순히 타입이 다른 인자를 받기 위해서 로직이 같은 함수를 여러개 만든다는 것은 유지,보수 관점에서 좋지 않다.

2.유니온 타입

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

const str = logText('hi');
str.split(""); //오류 발생
logNumber(10);

문자타입 인자를 문자열 api 'split'에 사용했음에도 오류가 발생한다. 정확한 타입을 인지해야 하는데 숫자타입이 들어오는지 문자타입이 들어오는지 모르기 때문에(숫자타입이 들어오는 경우에는 'split'이 제공되지 않음) 이와 같은 문제가 발생하는 것이다.

3.제네릭

function logText<T>(text: T): T {
  console.log(text);
  return text;
}
const str = logText<string>("hi");
str.split("");
logText<number>(10);

제네릭을 사용하여 앞의 문제점들을 해결할 수 있었다.
함수의 이름 바로 뒤에 <T>라는 코드를 추가하고, 함수의 인자와 반환 값에 모두 T라는 타입을 추가한다. 이렇게 되면 함수를 호출할 때 넘긴 타입에 대해 타입스크립트가 추정할 수 있게 된다.

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

//인터페이스 
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 };

제네릭 제약 조건

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

인자의 타입에 선언한 T는 아직 어떤 타입인지 구체적으로 정의하지않았기 때문에 length코드에서 오류가 발생한다. 해당 타입을 정의하지 않고도 length속성정도는 허용하려면 아래와 같이 작성해야 한다.

interface LengthWise {
  length: number;
}

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

length에 대해 동작하는 인자만 넘겨받을 수 있게된다.

비동기처리메서드 + 제네릭

동기적 코드 처리

반환값을 따로 작성하지 않아도 타입스크립트는 코드 내에서 타입을 추론할 수 있다.

  function fetchItems(): string[] {
  const fruit = ['apple', 'banana', 'cherry'];
  return fruit;
}

let result = fetchItems();
console.log(result);

비동기적 코드 처리

하지만 비동기적 코드를 실행한다면 프로미스 안에 들어오는 비동기 코드의 타입을 알 수가 없다. 프로미스는 기본적으로 제네릭을 이용하여 정의한다.

function fetchItems(): Promise<string[]> {
  const items = ['a', 'b', 'c'];
  return new Promise(resolve => {
    resolve(items);
  });
}
fetchItems();
profile
Lv.1🌷

0개의 댓글