Skip to main content

Generic

Intro

우리가 함수를 사용하는 이유는 무엇일까요? 행위의 추상화를 위해서 사용하기도 하지만 가장 핵심적인 기능은 특정 값을 넣었을때 특정 값을 반환하는 마치 자판기 같은 역할을 해주기 때문일 겁니다.

제너릭은 마치 타입의 함수 같습니다. 정적으로 선언하는 타입을 넘어, 확장 가능한 타입을 작성 할 수 있습니다.

pagination 데이터 타입을 예로 들어봅시다. pagination 은 api 서버의 부하를 줄이기위해 list 를 나누어 받는 식으로 구현이 됩니다. 아래 타입은 각각 'api/v1/post' 와 'api/v1/user' 응답 타입인데요. 문제는 없지만 page 와 count 를 연속적으로 작성하는 번거로움이 보입니다.

type PaginatedPosts = {
page: number; // 몇 페이지의 데이터인지
count: number; // data 의 전체 갯수
data: Post[];
}

type PaginatedUsers = {
page: number;
count: number;
data: User[];
}

genric 을 사용해서 아래와 같이 반복을 줄이고, 유연하게 작성이 가능합니다.

type Paginated<T> = {
page: number; // 몇 페이지의 데이터인지
count: number; // data 의 전체 갯수
data: T;
}

type PaginatedPosts = Paginated<Post[]>;
type PaginatedUsers = Paginated<User[]>

복수의 제너릭

함수의 인자 처럼 복수개의 제너릭을 선언 할 수 있습니다.

type Union<T1,T2,T3> = T1 | T2 | T2
type ExampleUnion = Union<string, number, { example: string }>
// ExampleUnion string | number | { example: string }

타입 제한 하기

ts 함수 처럼 인자의 타입을 제한 할 수 있습니다.

type MessageOf<T extends { message: unknown }> = T["message"];

type Email = { message: string; }
type Chat = { text: string; }

type EmailMessage = MessageOf<Email>
type Email = MessageOf<Chat> // Type Error

기본 타입

함수의 인자처럼 기본 타입 설정이 가능합니다.

type Union<T1 = number, T2 = number,T3 = number> = T1 | T2 | T2
type ExampleUnion1 = Union // number | number | number
type ExampleUnion1 = Union<string> // string | number | number
type ExampleUnion1 = Union<string, string> // string | string | number

함수 Generic

아래 함수의 기능은 배열 끝에 아이템을 추가하는 로직인데, typescript 상에선 string 밖에 대응하지 못합니다. 따라서 유연성이 떨어지는 함수라고 볼 수 있습니다.

const concat = (array: string[], item: string): string[] => [...array, item]

함수 제너릭은 함수가 유연하다면 함수에 맞게 유연한 타입정의를 가능하게 합니다.

// 인자의 타입이 동적이기 때문에, 작성시 넘겨준 인자 타입 바탕으로 동적으로 타입이 설정됩니다.
function concat<T> (array: T[], item:T):T[] { return [...array, item] }
//or
const concat = <T>(array: T[], item:T):T[] => [...array, item]


concat(["a", "b"], "c")
concat(["a", "b"], 3) // Type Error
concat([1, 2], 3)
concat([1, 2], "c") // Type Error

concat<string>(["a","b"], "c") // 제너릭 타입을 정적으로 정의 할 수 있습니다.