React + TypeScript AI Agent Conventions
React and TypeScript together have dozens of decision points. Here is how to encode every one of them so your AI writes consistent code.
Why the combination matters
React and TypeScript each have their own set of convention decisions. When combined, the number of decision points multiplies: How do you type component props -interface or type? Do you annotate the return type of components? How do you handle event handler types? Where do you define types relative to components? Your AI agent makes all these decisions based on training data -encoding your choices beats guessing.
Component + TypeScript conventions
The most impactful React+TypeScript rules: (1) Interface for props, always above the component. (2) Annotate component return type as JSX.Element or React.ReactNode. (3) Type event handlers explicitly (React.ChangeEvent<HTMLInputElement>). (4) Use React.FC sparingly -it hides the return type. Prefer function declarations. (5) Generics on custom hooks when the return type varies.
Combined conventions template
This section covers the React+TypeScript intersection specifically.
---
description: React + TypeScript combined conventions
globs: ["**/*.tsx"]
alwaysApply: true
---
# React + TypeScript Conventions
## Typing Components
- Props in an interface above the component (not inline):
✓ interface CardProps { title: string; count: number }
function Card({ title, count }: CardProps) { ... }
✗ function Card({ title, count }: { title: string; count: number }) { ... }
- Return type annotation on all exported components:
function Card({ title }: CardProps): JSX.Element { ... }
- Never use React.FC -it adds implicit children prop and hides return type.
## Event Handler Types
- Inline handlers: (e: React.MouseEvent<HTMLButtonElement>) => void
- Form submit: (e: React.FormEvent<HTMLFormElement>) => void
- Input change: (e: React.ChangeEvent<HTMLInputElement>) => void
## Hooks Typing
- useState: let TypeScript infer when obvious. Annotate when initial value is null/undefined:
const [user, setUser] = useState<User | undefined>(undefined)
- useRef: always annotate the element type:
const inputRef = useRef<HTMLInputElement>(null)
- Custom hooks: annotate return type explicitly with an interface.
## Children
- Prefer React.ReactNode for children prop (most permissive, rarely wrong).
- Use React.ReactElement if you need to clone or inspect the child.
- Use React.PropsWithChildren<YourProps> to add children to existing props.
## Generics in Hooks
- Add generics to hooks with varying return types:
function useFetch<TData>(url: string): { data: TData | undefined; isLoading: boolean }