Type inference
Infer data from a handler or a route object; do not duplicate the response interface.
Compatibility
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.