- 제네릭은 일반화된 데이터 타입으로 함수나 클래스 등의 내부에서 제네릭은 어떤 타입이든 될 수 있다.
함수의 제네릭
- 어떤 함수의 매개변수나 반환 값에 다양한 타입을 넣고 싶을 때 제네릭을 사용할 수 있다.
function fn<T>(arg: T): T {
return arg;
}
호출 시그니처의 제네릭
- 호출 시그니처는 타입스크립트의 함수 타입 문법으로 함수의 매개변수와 반환 타입을 미리 선언하는 것을 말한다. 타입 시그니처라고도 한다.
- 호출 시그니처를 사용할 때 제네릭 타입을 어디에 위치시키는지에 따라 타입의 범위와 제네릭 타입을 언제 구체 타입으로 한정할지 결정할 수 있다.
// foo를 사용할 때 타입을 명시함으로써 제네릭 타입을 구체 타입으로 한정
interface foo<T> {
fn: (arg: T) => T;
}
// Fn 타입의 함수를 실제 호출할 때 제네릭 타입을 구체 타입으로 한정
type Fn = <RequestData = void, ResponseData = void>(
baseURL: string
) => [RequestData, ResponseData];
제네릭 클래스
- 제네릭 클래스는 외부에서 입력된 타입을 클래스 내부에 적용할 수 있는 클래스이다.
- 제네릭 클래스를 사용하면 클래스 전체에 걸쳐 타입 매개변수가 적용된다. 특정 메서드만을 대상으로 제네릭을 적용하려면 해당 메서드를 제네릭 메서드로 선언하면 된다.
class LocalDB<T> {
async put(table: string, row: T): Promise<T> {
return new Promise<T>((resolved, rejected) => {});
}
async get(table: string, key: any): Promise<T> {
return new Promise<T>((resolved, rejected) => {});
}
}
class IndexedDB {
private _DB?: LocalDB<{ key: string, value: Promise<Record<string, unknown>>, keyPath: 'key' }>;
private DB() {
if (!this._DB) {
this._DB = new LocalDB();
}
return this._DB;
}
}
제한된 제네릭
- 타입스크립트에서 제한된 제네릭은 타입 매개변수에 대한 제약 조건을 설정하는 기능을 말한다.
- 타입을 제약하려면 타입 매개변수는 특정 타입을 extends 해야 한다.
- 타입 매개변수가 특정 타입으로 묶였을 때 키를 바운드 타입 매개변수, string을 키의 상한 한계라고 한다.
function fn<T extends string>(arg: T): T {
return arg;
}