제네릭
# 제네릭(Generics)이란?
타입스크립트를 사용하면 변수의 타입을 변경할 수 없다. name: string이라든지, age: number라든지, 변수 선언과 동시에 타입이 지정되기 때문이다. string | undefined 처럼 작성해주면 약간은 유연하게 사용할 수 있으나 기본적으로 타입은 항상 고정되어 있다.
그러나 프로그래밍을 하다보면 변수의 타입이 바뀔 수도 있다, 혹은 하나의 함수에 다양한 타입의 값을 넣어야 할 수도 있다. 이런 경우에는 타입을 고정적으로 지정하면 오히려 불편해진다. 따라서 타입을 직접적으로 고정시키지 않고 변수처럼 언제든지 변할 수 있도록 해주는 장치가 등장하였는데, 이를 제네릭(Generic)이라고 한다.
function add(x: string | number, y: string | number): string | number {
return x + y;
}
add(1, 2); // 3
add('hello', 'world'); // 'helloworld'
숫자 or 글자를 더하는 함수가 있다고 치자. 이때 타입을 string | number라고 지정해주면 될 것 같지만 문제가 있다. string + number 혹은 number + string이라는 경우가 있기 때문이다. 이 경우에는 타입 에러가 발생한다. 이 문제를 해결하기 위해서는 함수를 타입별로 나눠서 각각 선언해주어야 한다. 이를 함수 오버로딩이라고 한다.
function add(x: string, y: string): string;
function add(x: number, y: number): number;
function add(x: any, y: any) {
return x + y;
}
add(1, 2); // 3
add('hello', 'world'); // 'helloworld'
그렇다면 타입스크립트를 사용할 때 항상 함수 오버로딩 방식으로 함수를 이용해야 할까? 그럼 코드가 매우 길어질 것이다. 이로 인해 제네릭이 등장하였다.
function add<T>(x: T, y: T): T {
return x + y;
}
add<number>(1, 2);
add<string>('hello', 'world');
제네릭은 위와 같이 <>를 이용하여 표현한다. T라는 변수로 타입을 변수화하고, 함수를 사용할 때 타입을 지정하는 방식으로 사용한다. 즉, 타입을 변수처럼 선언한 뒤 그때그때마다 원하는 타입을 지정하여 사용하는 방식이다.
function example<T>(arr: T[]): T[] {
console.log(arr.length);
return arr;
}
example([1, 2, 3]);
배열로 사용하고 싶다면 배열 타입을 같이 선언해주면 된다.
# interface와 같이 사용하기
제네릭은 인터페이스와 같이 사용되는 경우가 많다. 예시로 알아보자.
interface User<T> {
name: string;
age: number;
option: T;
}
const user1: User<{ id: number; isLoggedIn: boolean }> = {
name: 'kim',
age: 20,
option: { id: 123; isLoggedIn: false },
};
const user2: User<string> = {
name: 's20',
price: 900,
option: 'hello',
};
이처럼 interface 내의 변수를 제네릭 타입으로 선언하면 다양한 데이터 자료를 할당할 수 있다.
참고 자료
'FE > TypeScript' 카테고리의 다른 글
[TypeScript] interface와 type의 차이점 (0) | 2023.02.25 |
---|---|
[TypeScript] TypeScript 알아보기 (0) | 2023.01.05 |