"React 19 added Actions and tightened the typing for Server Components. The TypeScript story finally feels complete."
Actions in React 19
React 19 introduced Actions — async functions that handle form submissions, data mutations, and pending states. <form action={createPost}> wires the action up to the form. The action receives a FormData, processes it, and the framework manages pending state.
Hooks like useTransition, useOptimistic, and the new useActionState integrate with Actions to give you ergonomic patterns for optimistic updates and form state. TypeScript types all of these correctly out of the box.
Server Components — async functions returning JSX
A Server Component is a React component that runs on the server. In TypeScript, this means an async function that returns JSX. export default async function Page() { const data = await fetchData(); return <div>{data.title}</div> } — the function is async, can await directly, and TypeScript types the return as Promise<React.ReactNode>.
Client Components stay synchronous. Marking a file with 'use client' at the top means everything in it runs in the browser. The compiler treats them differently: server components can be async; client components can use hooks.
The split is at the boundary
A server component can render a client component as a child. A client component cannot import a server component directly (because the server code wouldn't make sense in the browser). The TypeScript types reflect this split — most of the time it just works, but the error messages when you cross the line are clear enough to fix.