타입스크립트의 제너릭
제너릭을 안 쓸때의 문제점
타입스크립트의 제너릭은 무엇일까? 일단 제너릭을 알기전에 제너릭을 안쓸때의 문제점을 보자
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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, 4]);
superPrint([true, false, true]);
superPrint(["a", "b", "c"]);
superPrint([1, 2, true, false]);
배열의 내용을 하나씩 다 출력하는 함수를 만든다고 했을때 type에 알지 못하는 타입의 배열의 타입이 들어갈 경우 타입에 일일이 하나씩 정의를 해야되는 문제가 발생한다.
제너릭으로의 해결
코드를 제너릭을 사용하면 다음과 같이 간단하게 정리가 된다.
1
2
3
4
5
6
7
8
9
10
11
12
13
type SuperPrint = {
// 제너릭을 통해 타입을 간단히 정리하였다.
<T>(arr: T[]): 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]);
<T>
에서 call signature를 맞춰줌으로써 타입에 대한 값이 생긴다.
다수의 제너릭을 사용하는 방법
제너릭은 인자 들어가는 부분부터 타입이 인지가 되기에 두개를 쓸때는 아래와 같이 사용한다.
1
2
3
4
5
6
7
8
9
10
11
12
type SuperPrint = {
<T, M>(arr: T[], value: M): void;
};
const superPrint: SuperPrint = (arr, val) => {
arr.forEach((i) => console.log(i));
};
superPrint([1, 2, 3, 4], "x");
superPrint([true, false, true], 1);
superPrint(["a", "b", "c"], true);
superPrint([1, 2, true, false], []);
function 으로 Generics 정의하기
1
2
3
4
5
6
7
8
9
10
11
12
function superPrint1<T>(a: T[]) {
return a[0];
}
superPrint1([1, 2, 3, 4]);
// superPrint1<boolean>([1, 2, 3, 4]); // error!
// 제너릭으로 타입을 직접 정의할 수 있지만 TypeScript가 자연스럽게 처리 되도록 하는게 좋다.
superPrint1([true, false, true]);
superPrint1(["a", "b", "c"]);
superPrint1([1, 2, true, false]);
함수에서 superPrint1<boolean>([1, 2, 3, 4])
와 같이 제너릭을 직접적으로 선언할 수 도 있지만, 자연스럽게 타입스크립트에서 처리되도록 할 수 있는게 좋다.
type에서 Generics 사용하기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
type Player<E> = {
name: string;
extraInfo: E;
};
type Extra = {
HP: number;
};
type ParkPlayer = Player<Extra>;
const Park: ParkPlayer = {
name: "park",
extraInfo: {
HP: 1000
}
};
const Lee: Player<null> = {
name: "Lee",
extraInfo: null
};
타입 안에 타입형식으로 다음과 같이도 사용할 수 있다.
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.