smolter
Guides

Type inference

Infer data from a handler or a route object; do not duplicate the response interface.

Compatibility

ReactAvailable in this renderer's browser integration.
React SSRAvailable to this renderer's SSR integration; browser event handlers run after hydration.
PreactAvailable in this renderer's browser integration.
Preact SSRAvailable to this renderer's SSR integration; browser event handlers run after hydration.

Handler inference

Pass typeof loader as the hook generic. TypeScript cannot infer a nearby exported function just because it lives in the same file. The generic is erased at runtime. Data may be undefined before the first completed load.

import type { clientLoader } from "./loader";
import type { clientAction } from "./action";

const data = useLoaderData<typeof clientLoader>();
const fetcher = useFetcher<typeof clientAction>();
const revalidate = useRevalidator();
const busy = fetcher.state !== "idle";

Route inference

Passing a typed defineRoute result allows automatic inference with no hook generic. A bound data hook returns undefined if a different route is active.

const taskRoute = defineRoute("/tasks/:id", taskModule);

const data = useLoaderData(taskRoute);
const fetcher = useFetcher(taskRoute);

Mixed results

A fetcher bound to a route can both load and submit, so its data type includes the loader and action results. Narrow that union before reading fields unique to one result. LoaderData and ActionData similarly include server and client handler results.

Transport boundary

Server data must survive JSON serialization. Dates become strings; functions and class instances do not retain behavior. serverLoader and serverAction return unknown at the raw transport boundary: validate or narrow the payload before using it.