Generic Component
Problem
You create separate Table, List, or Select components for each data type - UserTable, ProductTable, OrderTable - duplicating the same logic with minor type differences. Type safety breaks when components pass data around because TypeScript can’t infer the specific type being used.
Solution
Create components that work with different data types through generics rather than hardcoding specific types. This makes components reusable across contexts while preserving type safety.
Example
This example demonstrates a generic List component that works with any data type while preserving type safety through TypeScript generics.
// Define props interface with generic type parameter T
interface ListProps<T> {
items: T[]; // Array of any type
renderItem: (item: T) => React.ReactNode; // Function to render each item
}
// Generic function component that works with any type T
function List<T>({ items, renderItem }: ListProps<T>) {
return <ul>{items.map(renderItem)}</ul>;
}
// Usage: TypeScript infers T is User type from the items prop
<List items={users} renderItem={(user) => <li>{user.name}</li>} />
Benefits
- Eliminates code duplication by creating one component that works with multiple types.
- Preserves type safety while maintaining flexibility across different data structures.
- Enables better type inference so TypeScript understands what data you’re working with.
- Makes components more maintainable by centralizing logic in a single implementation.
Tradeoffs
- Increases complexity with generic syntax that can be harder to read and understand.
- Can make components more abstract and harder to debug when types don’t match.
- May require explicit type parameters when TypeScript can’t infer the type automatically.
- Not worth the complexity for components that only work with one or two types.