제너릭 타입(Generic Type)은 ts와 같은 정적 프로그래밍 언어에서 코드의 재사용성을 높이기 위해 사용되는 기능이다. 제너릭 타입을 사용하면 특정 타입에 의존하지 않고, 다양한 타입을 처리할 수 있는 함수를 정의하거나 클래스를 작성할 수 있다는 장점이 있다.
react의 컴포넌트에도 제너릭 타입을 적용할 수 있다. 제너릭 타입을 사용하면 컴포넌트가 다양한 타입을 받을 수 있게 되어, 재사용성을 높일 수 있다. 다음은 리액트 컴포넌트에 제너릭 타입을 입히는 방법에 살펴보자.
함수형 컴포넌트에 제너릭 타입을 적용하는 기본 구조는 다음과 같다.
interface Props<T> {
items: T[]
renderItem: (item: T) => React.ReactNode
}
const List = <T,>({ items, renderItem }: Props<T>) => {
return (
<ul>
{items.map((item, index) => (
<li key={index}>{renderItem(item)}</li>
))}
</ul>
)
}
interface Props<T>
const List = <T,>({ items, renderItem }: Props<T>
<T>
를 사용하면 이를 제너릭이 아닌 컴포넌트의 태그로 인식하기 때문에, 사이에 쉼표(,) 를 넣어주어야 한다. 위의 제너릭 컴포넌트는 아래와 같은 방법으로 사용할 수 있다.
interface User {
id: number;
name: string;
}
interface Post {
id: number;
title: string
}
const users: User[] = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
];
const posts: Post[] = [
{ id: 1, title: 'For Job' },
{ id: 2, title: 'Currently Trends' },
];
const App = () => {
return (
<div>
<h1>User List</h1>
<List<User>
items={users}
renderItem={(user) => <div>{user.name}</div>}
/>
<List<Post>
items={posts}
renderItem={(post) => <div>{post.name}</div>}
/>
</div>
);
};
제너릭 타입에 제약 조건을 추가하여 특정 속성이 있는 타입만 받도록 할 수 있다. 예를 들어, length 속성이 있는 타입만 받도록 하는 경우에는 다음과 같이 작성할 수 있다.
interface Props<T extends { length: number }> {
items: T[];
renderItem: (item: T) => React.ReactNode;
}
const List = <T extends { length: number }>({ items, renderItem }: Props<T>) => {
return (
<ul>
{items.map((item, index) => (
<li key={index}>{renderItem(item)}</li>
))}
</ul>
);
};
React.FC (또는 React.FunctionComponent) 타입에 제너릭을 사용하는 것은 가능하다. 단, 제네릭 Props에 T값을 할당해줘야 타입 에러가 뜨지 않기 때문에,unknown
을 넣어준다.
import { FC } from 'react'
interface Props<T> {
items: T[]
renderItem: (item: T) => React.ReactNode
}
const List:FC<Props<unknown>> = <T,>({
items,
renderItem,
}: Props<T>) => {
return (
<ul>
{items.map((item, index) => (
<li key={index}>{renderItem(item)}</li>
))}
</ul>
)
}