React TypeScript Development
Core Patterns
Component Structure
import { type FC, type ReactNode } from 'react';
interface ComponentProps { children?: ReactNode; variant?: 'primary' | 'secondary'; disabled?: boolean; onClick?: () => void; }
export const Component: FC<ComponentProps> = ({
children,
variant = 'primary',
disabled = false,
onClick,
}) => {
return (
<div
className={component component--${variant}}
data-disabled={disabled}
onClick={disabled ? undefined : onClick}
>
{children}
</div>
);
};
Typing Guidelines
Pattern Use
FC<Props>
Standard functional components
ReactNode
Children, any renderable content
ComponentPropsWithoutRef<'button'>
Extend native HTML element props
forwardRef<HTMLDivElement, Props>
Components needing ref forwarding
Event Handler Types
onClick?: (event: React.MouseEvent<HTMLButtonElement>) => void; onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void; onSubmit?: (event: React.FormEvent<HTMLFormElement>) => void; onKeyDown?: (event: React.KeyboardEvent<HTMLInputElement>) => void;
Custom Hooks Pattern
import { useState, useCallback } from 'react';
interface UseToggleReturn { value: boolean; toggle: () => void; setTrue: () => void; setFalse: () => void; }
export const useToggle = (initialValue = false): UseToggleReturn => { const [value, setValue] = useState(initialValue);
const toggle = useCallback(() => setValue(v => !v), []); const setTrue = useCallback(() => setValue(true), []); const setFalse = useCallback(() => setValue(false), []);
return { value, toggle, setTrue, setFalse }; };
Context Pattern
import { createContext, useContext, type FC, type ReactNode } from 'react';
interface ThemeContextValue { theme: 'light' | 'dark'; toggleTheme: () => void; }
const ThemeContext = createContext<ThemeContextValue | null>(null);
export const useTheme = (): ThemeContextValue => { const context = useContext(ThemeContext); if (!context) throw new Error('useTheme must be used within ThemeProvider'); return context; };
File Naming
ComponentName/ ├── ComponentName.tsx # Implementation ├── ComponentName.types.ts # Types (optional) ├── ComponentName.stories.tsx # Storybook ├── index.ts # Exports
Best Practices
-
Explicit return types for public functions
-
Discriminated unions for complex state
-
as const for literal types
-
Generic components for reusable patterns
-
Handle undefined explicitly
Integration
-
Atomic Design: See atomic-design skill for hierarchy
-
CSS Tokens: See css-tokens skill for styling
-
Storybook: See storybook skill for docs