Why Combine React with TypeScript?
TypeScript provides compile-time type safety, catches bugs early, and dramatically enhances Developer Experience with rich auto-completion in modern IDEs.
Tip 1: Use ComponentPropsWithoutRef
Instead of re-declaring HTML attributes manually:
import { ComponentPropsWithoutRef } from 'react';
interface ButtonProps extends ComponentPropsWithoutRef<'button'> {
variant?: 'primary' | 'secondary';
}
export function Button({ variant = 'primary', children, ...props }: ButtonProps) {
return <button className={`btn-${variant}`} {...props}>{children}</button>;
}
Tip 2: Use Discriminated Unions for Async State
Avoid conflicting boolean flags:
type AsyncState<T> =
| { status: 'idle' }
| { status: 'loading' }
| { status: 'error'; error: Error }
| { status: 'success'; data: T };
Tip 3: Generic Component Props
Create reusable components like select dropdowns or data tables using generics:
interface ListProps<T> {
items: T[];
renderItem: (item: T) => React.ReactNode;
}
export function List<T>({ items, renderItem }: ListProps<T>) {
return <div>{items.map(renderItem)}</div>;
}
Conclusion
Mastering these patterns ensures high scalability, reliability, and ease of refactoring across large codebase applications.