TypeScript with React
Practical typing patterns for components, hooks, and events under strict TypeScript.
Busque em todas as páginas da documentação
Practical typing patterns for components, hooks, and events under strict TypeScript.
🤖 Read the SystemsArchitect.io Blog for over 100+ cloud architecture articles 🔥
Declare props as a named type or interface and annotate the parameter. Export the type when parents construct props objects.
type AvatarProps = { src: string; alt: string; size?: number };
function Avatar({ src, alt, size = 40 }: AvatarProps) {
return <img src={src} alt={alt} width={size} height={size} />;
}Use React.ReactNode for anything renderable as children. Narrow only when you truly require a single element.
type BoxProps = { children: React.ReactNode };
function Box({ children }: BoxProps) {
return <div className="box">{children}</div>;
}Prefer React's synthetic event types. ChangeEvent for inputs, FormEvent for forms, MouseEvent for clicks.
function onChange(e: React.ChangeEvent<HTMLInputElement>) {
setValue(e.target.value);
}
function onSubmit(e: React.FormEvent<HTMLFormElement>) {
e.preventDefault();
}Infer when the initial value is precise; pass a generic when the initial value is wider (e.g. null union).
const [user, setUser] = useState<User | null>(null);
const [count, setCount] = useState(0); // inferred numberType host refs with the concrete element interface. Start as null until React attaches the node.
const inputRef = useRef<HTMLInputElement>(null);
inputRef.current?.focus();For mutable boxes that always hold a value after init, use a definite type and assign .current yourself.
const idRef = useRef(0);
idRef.current += 1;React.ComponentProps<"button"> pulls the prop type of a host tag or another component for clean extension.
type BtnProps = React.ComponentProps<"button"> & { loading?: boolean };Utility that adds optional children to your props type when you do not want to declare it manually.
type CardProps = React.PropsWithChildren<{ title: string }>;Model variants with a shared discriminant so TypeScript narrows related fields correctly.
type AlertProps =
| { kind: "error"; error: Error }
| { kind: "success"; message: string };
function Alert(props: AlertProps) {
if (props.kind === "error") return <p>{props.error.message}</p>;
return <p>{props.message}</p>;
}Parameterize item type so map callbacks stay typed without casting.
type ListProps<T> = {
items: T[];
getKey: (item: T) => string;
renderItem: (item: T) => React.ReactNode;
};
function List<T>({ items, getKey, renderItem }: ListProps<T>) {
return <ul>{items.map((item) => <li key={getKey(item)}>{renderItem(item)}</li>)}</ul>;
}Give createContext an explicit type. Start with null and narrow in a custom hook for required providers.
type Auth = { user: User; logout: () => void };
const AuthContext = createContext<Auth | null>(null);Read another component's props without exporting a separate type using React.ComponentProps<typeof Comp>.
type RowProps = React.ComponentProps<typeof Row>;Use as const on config objects so string fields stay literal unions instead of widening to string.
const tones = ["info", "danger", "success"] as const;
type Tone = (typeof tones)[number];satisfies checks a value against a type while preserving narrower inferred literals.
const routes = {
home: "/",
docs: "/docs",
} satisfies Record<string, string>;Prefer an explicit props parameter. React.FC historically implied children and obscures generic components.
// Prefer:
function Button(props: ButtonProps) { return <button {...props} />; }
// Avoid: const Button: React.FC<ButtonProps> = (props) => ...Stack versions: React 19 · TypeScript (strict) ·
@types/reactmatching React 19
Revisado por Chris St. John·Última atualização: 19 de jul. de 2026
🤖 Read the SystemsArchitect.io Blog for over 100+ cloud architecture articles 🔥