TypeScript 제네릭
TypeScript의 제네릭에 대해 알아보겠습니다.
1. 제네릭
TypeScript는 정적 타입 언어이기 때문에 함수 또는 클래스를 선언할 때 매개변수나 반환값의 타입을 정의해야 합니다. 하지만 이렇게 특정 타입을 위해 만들어진 함수나 클래스를 재사용 해야하는 경우가 발생하고 이 때 제네릭을 사용합니다.
2. 제네릭이 필요한 경우
다음은 자료구조 큐(Queue)를 TypeScript로 구현한 예제입니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | class Queue { protected data: any = []; constructor() {} push(item: any): void { this.data.push(item); } pop(): void { return this.data.shift(); } } const queue = new Queue(); queue.push(0); queue.push('1'); console.log(queue.pop().toFixed()); // 0 console.log(queue.pop().toFixed()); // Runtime error | cs |
Number.prototype.toFixed()는 매개변수로 지정된 소수점 자리를 반올림하여 문자열로 반환
Queue 클래스에서 선언한 data 배열은 any 타입이기 때문에 어떠한 타입이든 추가할 수 있는데 이러한 경우 자료형의 타입이 동일하지 않다는 문제가 발생하게 됩니다.
이러한 경우 타입 검사를 하거나 다음과 같이 상속을 통해 해결하는 방법이 있습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | class Queue { protected data: any[] = []; push(item: any): void { this.data.push(item); } pop(): void { return this.data.shift(); } } class NumberQueue extends Queue { push(item: number) { super.push(item); } pop(): number { return super.pop(); } } | cs |
하지만 다양한 타입에 대해 사용해야 할 경우엔 타입 별로 클래스를 상속받아 추가해야 하므로 코드의 양이 늘어나고 번거롭게 됩니다. 따라서 제네릭의 사용이 필요하게 됩니다.
3. 제네릭의 사용
앞서 알아본 예제를 제네릭을 사용하여 다음과 같이 정의할 수 있습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | class Queue<T> { protected data: Array<T> = []; push(item: T) { this.data.push(item); } pop(): T { return this.data.shift(); } } const numberQueue = new Queue<number>(); const stringQueue = new Queue<string>(); |
클래스에서의 제네릭은 타입 선언부에 <T> 를 추가하여 사용합니다. T는 Type의 약자로 제네릭 선언시 관용적으로 많이 사용하며 Type Parameter라고 합니다.
위의 예제에서 객체 생성 부분을 보면 제네릭은 선언 시점이 아니라 생성 시점에 타입을 명시하여 다양한 타입의 사용이 가능하게 한다는 것을 알 수 있습니다.
또한 다음과 같이 함수에도 제네릭을 사용할 수 있습니다. 함수도 마찬가지로 선언부에 제네릭을 사용해줍니다. 함수의 매개변수에 따라서 타입이 정의되는 것을 알 수 있습니다.
1 2 3 4 5 6 7 8 9 | function reverse<T>(items: T[]): T[] { return items.reverse(); } const numberArr = [1, 2, 3, 4, 5]; const objectArr = [{ name: 'Harry' }, { name: 'Kim' }]; console.log(reverse(numberArr)); // [ 5, 4, 3, 2, 1 ] console.log(reverse(objectArr)); // [ { name: 'Kim' }, { name: 'Harry' } ] | cs |
이상으로 TypeScript의 제네릭에 대해 알아봤습니다.
※ Reference
이웅모 지음, 『Angular Essentials』, 루비페이퍼(2018), p143 ~ p.147 4.7 제네릭
poiemaweb.com, 제네릭, https://poiemaweb.com/typescript-generic
hyunseob.github.io, TypeScript: 제네릭(Generic), https://hyunseob.github.io/2017/01/14/typescript-generic/