Typescript Polymorphism

최재홍·2023년 10월 8일
0
post-custom-banner

Polymorphism(다형성)

poly = many, multi, several ...
morpho = structure, ...

many different structure

example

첫번째 call signature을 만들어보자.

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

SuperPrint는 number로 된 arr를 인자로 받고 void를 return한다.

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

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

이렇게 인자로 들어올 배열의 요소들을 print하는 call signature이다.

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

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

superPrint([1, 2, 3, 4])
superPrint([true, false, true])

이렇게 call signature에 대한 인자 타입을 하나 더 지정해줌으로써 최하단의 superPrint함수 두개가 정상적으로 동작하게 되었다.

superPrint(["a", "b", "c"])

하지만 이렇게 문자열로 이루어진 배열이 인자로 들어간 함수는 정상동작하지 않는다.
그렇다면 위의 과정과 같이

(arr: string[]):void

를 추가해줘야 할까?

이론상으로는 이렇게 하면 정상적으로 동작하지만 정답은 아니다.
다형성을 활용하는 더 좋은 방법이 있다.

내가 하고 싶은건 인자로 들어갈 배열의 요소로 어떤 타입의 데이터가 포함되어 있어도 정상적으로 동작하게끔 만드는 것이다.

(arr: (number|boolean)[]):void

이런식으로 인자에 대해서 처리하는 것도 완전한 방법은 아니다. 인자로 들어갈 데이터의 타입에 대해 모든 경우의 수에 대해서 고려해야만 하기 때문이다.
그래서 그 대신 'generic'을 활용할 필요가 있다.
generic은 타입의 placeholder 같은 것이다.

다시 말해서 generic을 사용하는 이유는 call signature를 작성할 때, 변수에 대한 타입을 확신할 수 없을 때에도 함수가 동작하게끔 만들기 위해서다. 어떤 타입에 대해서도 일단 동작하게 만드는 것이다.

generic을 사용하는 방법

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

여기서 <>안에 들어가는 것이 이 generic에 대한 이름이 된다.

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

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

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

여기서 return값에 대한 타입을 바꿔줄 수도 있다.

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

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

const a = superPrint([1, 2, 3, 4])
const b = superPrint([true, false, true])
const c = superPrin(["a", "b", "c"])
const d = superPrint([1, 2, true, false])

여기서 TypePlaceholder는 단순히 이름일 뿐이므로 일반적으로 T나 V로 짧게 사용하는 경우가 많다.
요는 <>안에 placeholder로서의 generic의 이름을 씀으로써 확정되지 않은 타입에 대한 call signature를 작성할 수 있게 되는 것이다.

post-custom-banner

0개의 댓글