제네릭 정의
제네릭(Generics)이란 타입을 마치 함수의 파라미터처럼 사용하는 것을 의미한다.
제네릭을 사용하면 클래스나 함수 인터페이스를 다양한 타입으로 재사용할 수 있다.
예를 들어, 다음과 같은 함수를 실행하려고 한다.
function getSize(arr): number {
return arr.length;
}
위의 함수는 리스트의 길이를 반환해주는 함수이다. 만약 리스트의 요소들이 숫자형, 문자형 등 다양한 타입들로 되어 있다면 어떻게 처리해주어야 할까?
function getSize(arr: any): number {
return arr.length;
}
getSize([1, 2, 3]);
getSize(["a", "b", "c"]);
getSize([true, false, true]);
첫 번째는 arr의 타입을 any로 처리하면 된다. 하지만 이 것은 어떤 타입이 들어가도 상관없기 때문에 타입스크립트의 장점을 살릴 수 없다.
function getSize(arr: number[] | string[] | boolean[]): number {
return arr.length;
}
getSize([1, 2, 3]);
getSize(["a", "b", "c"]);
getSize([true, false, true]);
두 번째 방법은 옵셔널하게 주어 타입을 제한할 수 있다. 하지만 객체형 리스트 등 또 다른 타입의 리스트가 들어오면 추가적으로 타입을 작성해야 하기 때문에 매우 불편하다.
위의 문제들을 해결하기 위해서 제네릭을 사용한다.
제네릭 사용 방법
제네릭은 함수나 인터페이스 뒤에 < > 을 붙이고, 사이에 T(일반적)를 사용한다.
여기서 T는 제네릭을 선언할 때 관용적으로 사용되는 식별자로 타입 파라미터라 한다.
제네릭을 사용하여 위의 함수를 다시 구현하면, 아래와 같이 할 수 있다.
function getSize<T>(arr : T[]): number {
return arr.length;
}
getSize<number>([1, 2, 3])
getSize<string>(["a", "b", "c"]);
getSize<boolean>([true, false, true]);
다른 타입의 리스트가 들어온다면, 다음과 같이 구현할 수 있다.
function getSize<T>(arr : T[]): number {
return arr.length;
}
getSize<number>([1, 2, 3])
getSize<string>(["a", "b", "c"]);
getSize<boolean>([true, false, true]);
getSize([{name : "Tom"}, {}, {}]); # 타입을 지정 해주지 않아도 타입스크립트는 전달되는 매개변수의 타입을 알기 때문에 생략 가능.
인터페이스 제네릭
제네릭은 인터페이스에 적용할 수도 있다.
interface Car<T> {
name: string;
price: number;
option: T; // 여러 가지 타입이 올 수 있다는 것을 지정
}
const c1: Car<{ color: string; year: number }> = {
name: "c10",
price: 1000,
option: {
color: "red",
year: 2000,
},
};
const c2: Car<string> = {
name: "c11",
price: 500,
option: "nice",
};
제네릭 제약 조건 (extends)
제네릭에 extends 키워드를 이용하면 제네릭 타입으로 입력할 수 있는 타입의 종류를 제한할 수 있다.
<T extends K> 형태의 제네릭이 있다면, T가 K에 할당 가능해야 한다 라고 정의한다.
interface User {
name: string;
age: number;
}
interface Car {
name: string;
color: string;
}
interface Book {
name: number;
price: number;
}
const user: User = { name: "a", age: 10 };
const car: Car = { name: "bmw", color: "red" };
const book: Book = { name: 1, price: 3000 };
function showName<T extends { name: string }>(data: T): string {
return data.name;
}
showName(user);
showName(car);
showName(book); // name의 타입이 string이 아니므로 error를 반환
'프로그래밍 언어 > Typescript' 카테고리의 다른 글
[타입스크립트] 리터널 타입과 유니온 타입, 교차 타입 (0) | 2024.01.15 |
---|---|
[타입스크립트] interface 활용 (1) | 2023.12.21 |
[타입스크립트] 기본 타입 (0) | 2023.12.18 |
[타입스크립트] 개념 및 배경 (0) | 2023.12.13 |