type ListProps<T> = {
items: T[];
getKey: (item: T) => string;
render: (item: T) => React.ReactNode;
};
function List<T>({ items, getKey, render }: ListProps<T>) {
return <ul>{items.map((item) => <li key={getKey(item)}>{render(item)}</li>)}</ul>;
}
<List items={users} getKey={(u) => u.id} render={(u) => u.name} />
Make the component a generic function: function List<T>(props: ListProps<T>). A component is just a function, so it can take a type parameter like any generic function.
The props type is generic over T. T links items to the getKey and render callbacks.
At the call site you do not write T. TypeScript infers it from items. So if users is User[], the u parameter in both callbacks is a User. You get autocompletion, and typos become errors.
One catch in a .tsx file: a generic arrow function like <T>(props) => ... can look like a JSX tag to the compiler. So people write <T,>, or use a function declaration, which avoids the problem.
- React components can be generic functions.
Tlinksitemswith the callbacks.- TypeScript infers
Tfrom the props at the call site. - Generic arrow functions in
.tsxneed<T,>, or use a function declaration.
Read more