본문 바로가기
TypeScript

[타입스크립트] 다형성(polymorphism)과 제네릭(generic)

by 메이플 🍁 2022. 11. 3.

다형성(polymorphism)이란?

polymorphism이란 poly(many) + morphos(form)의 합성어로 다수의 형태라는 의미다

 

다형성이 없다면?

아래의 예제처럼 사용할 모든 타입을 미리 정의해주어야한다

type SuperPrint = {
  (arr: number[]): void
  (arr: boolean[]): void
  (arr: string[]): void
  (arr: (number|boolean)[]): void
}

const superPrint: SuperPrint = (arr) => {
  arr.forEach(i => console.log(i))
}

superPrint([1, 2, 3])
superPrint([true, false, true])
superPrint(['a', 'b', 'c'])
superPrint([1, 2, true, false])

 

generic을 사용해 call signature에 다형성 주기

제네릭이란 타입스크립트에게 타입을 유추하도록 만들어주는 키워드다

제네릭은 선언 시점이 아니라 생성 시점에 타입을 명시하여 하나의 타입만이 아닌 다양한 타입을 사용할 수 있도록 하는 기법이다

함수의 타입이 여러개일경우 generic을 사용해 call signature에 다형성을 준다

아래의 예제처럼 특정타입을 지정하고 싶지 않을때는 타입에 제네릭을 선언해준다

type SuperPrint = {
  <제네릭이름>(arr: 제네릭이름[]): void
}

const superPrint: SuperPrint = (arr) => {
  arr.forEach(i => console.log(i))
}

superPrint([1, 2, 3])
superPrint([true, false, true])
superPrint(['a', 'b', 'c'])
superPrint([1, 2, true, false])

리턴값이 다양한 경우에도 제네릭을 사용해준다

type SuperPrint = {
  <제네릭이름>(arr: 제네릭이름[]): 제네릭이름
}

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

console.log(
  superPrint([1, 2, 3]),
  superPrint([true, false, true]),
  superPrint(['a', 'b', 'c']),
  superPrint([1, 2, true, false])
)

일반적으로 영문자 T를 제네릭 이름으로 많이 사용한다

제네릭 이름은 반드시 대문자로 시작해야한다

type SuperPrint = {
  <T>(arr: T[]): void
}

제네릭을 여러번 선언할수도 있다

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

 

일반함수에 generic 사용하기

function superPrint<T>(a: T[]) {
  return a[0]
}

superPrint([1, 2, 3])

 

타입선언시 generic 사용하기

type Player<T> = {
  name: string,
  extraInfo: T
}

const maple: Player<{favFood: string}> = {
  name: 'maple',
  extraInfo: {
    favFood: 'pizza'
  }
}
type Player<T> = {
  name: string,
  extraInfo: T
}

type maplePlayer = Player<{favFood: string}>

const maple: maplePlayer = {
  name: 'maple',
  extraInfo: {
    favFood: 'pizza'
  }
}
type Player<T> = {
  name: string,
  extraInfo: T
}

type mapleExtra = { favFood: string }
type maplePlayer = Player<mapleExtra>

const maple: maplePlayer = {
  name: 'maple',
  extraInfo: {
    favFood: 'pizza'
  }
}

 

타입스크립트에 내장되어 있는 기본타입

타입스크립트에 있는 모든 기본 타입들은 제네릭으로 만들어져 있다

type A = Array<number>

let a:A = [1, 2, 3]

 

generic vs any

얼핏 보기에 generic과 any는 같은것처럼 보이나 둘은 완전히 다르다. generic을 선언하면 타입스크립트에서 자동으로 사용하는 타입을 만들어주고 any를 사용하면 타입스크립트를 탈출해 일반 자바스크립트처럼 사용하게된다.

댓글