Tillbaka till bloggen
Development9 min read
TypeScript Patterns for Better React Applications
AT
Alex Thompson
28 november 2024
TypeScript and React are a powerful combination. Here are patterns that will improve your type safety and developer experience.
Discriminated Unions for State
Instead of boolean flags, use discriminated unions:
// Avoid
type State = {
loading: boolean;
error: Error | null;
data: Data | null;
};
// Better: Discriminated union
type State =
| { status: 'idle' }
| { status: 'loading' }
| { status: 'error'; error: Error }
| { status: 'success'; data: Data };This pattern eliminates impossible states and makes handling each case explicit.
Generic Components
Create reusable components with generics:
interface ListProps<T> {
items: T[];
renderItem: (item: T) => React.ReactNode;
keyExtractor: (item: T) => string;
}
function List<T>({ items, renderItem, keyExtractor }: ListProps<T>) {
return (
<ul>
{items.map(item => (
<li key={keyExtractor(item)}>
{renderItem(item)}
</li>
))}
</ul>
);
}Polymorphic Components
Build components that can render as any element:
type ButtonProps<T extends React.ElementType> = {
as?: T;
children: React.ReactNode;
} & React.ComponentPropsWithoutRef<T>;
function Button<T extends React.ElementType = 'button'>({
as,
children,
...props
}: ButtonProps<T>) {
const Component = as || 'button';
return <Component {...props}>{children}</Component>;
}
// Usage
<Button>Click me</Button>
<Button as="a" href="/path">Link button</Button>Type-Safe Event Handlers
Avoid any in event handlers:
function handleChange(e: React.ChangeEvent<HTMLInputElement>) {
const value = e.target.value;
// value is typed as string
}
function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
e.preventDefault();
const formData = new FormData(e.currentTarget);
}Const Assertions for Config
Use const assertions for configuration objects:
const ROUTES = {
home: '/',
about: '/about',
blog: '/blog',
} as const;
type Route = typeof ROUTES[keyof typeof ROUTES];
// Type: '/' | '/about' | '/blog'Conclusion
These patterns leverage TypeScript's type system to catch errors at compile time and improve the development experience. Start incorporating them gradually into your codebase.
Author
AT
Alex Thompson
Lead Developer
Alex is a full-stack developer with 8+ years of experience building web applications. He specializes in React, Next.js, and cloud architecture.