Typescript-challenge 4

January·2022년 6월 30일
0

Generics (제네릭)

제네릭은 재사용성이 높은 컴포넌트를 만들 때 자주 활용되는 특징이다. 한가지 타입보다 여러 가지 타입에서 동작하는 컴포넌트를 생성하는데 사용된다.

// 기본 문법
function getText <T>(text: T): T {
  return text;
}
// <T>는 placeholder이다.

// 함수 호출할 때 함수 안에서 사용할 타입을 넘겨준다.
getText<string>('hi');
getText<number>(10);
getText<boolean>(true);

// string으로 호출 됐을 때 동작
function getText <string>(text: string): string {
  return text;
}

제네릭은 내가 요구한 대로 signature를 생성해줄 수 있는 도구이다.

제네릭(Generics)의 사전적 정의

type SuperPrint = <T, M>(a: T[], b: M) => T

const superPrint: SuperPrint = (a, b) => a[0]

superPrint([1, 2, true, false, "hello"], "bye") 

타입스크립트는 제네릭을 처음 인식했을 때와 제네릭의 순서를 기반으로 제네릭의 타입을 알게된다.

any와 차이점

type SuperPrint = (a: any[]) => any

const superPrint: SuperPrint = (a) => a[0]

const d = superPrint([1, 2, true, false, "hello"]) 
d.toUpperCase()  // 에러나지 않음.

any를 쓰면 어떤 타입이 와도 무관하기 때문에 toUpperCase에 에러를 잡아내지 못한다. 제네릭을 사용할 때 타입스크립트가 해당 함수의 call signature를 만들어주기 때문에 에러를 발생시킬 수 있다. 즉, 보호를 받을 수 있다.

결론

// type SuperPrint = <T, M>(a: T[], b: M) => T
// const superPrint: SuperPrint = (a, b) => a[0]

// 다른 모양
function superPrint<T>(a: T[]) {
  return a[0]
}

제네릭은 타입을 생성할 수도 있고 타입을 확장할 수도 있다.

type Player<E> = {
  name: string
  extraInfo: E
}
type NicoExtra = {
  favFood: string
}
type NicoPlayer = Player<NicoExtra>

const nico: NicoPlayer = {
  name: "nico"
  extraInfo: {
    favFood: "ramen"
  }
}

타입을 생성하고 그 타입을 또다른 타입에 넣어서 사용할 수 있다. Player타입에서 하나가 달라질 수 있는 타입이라면 그게 E이고 E에 제네릭을 넣어서 사용한다. 그럼 Player 타입을 재활용할 수 있는 기회를 많이 가진다.

0개의 댓글