Point0by 1gr14
  • Меню
    • GitHub
    • Блог
  • Introduction
    • Overview
    • Getting Started
    • Full Overview
    • Benchmarks
    • Points
  • Points
    • Page
    • Layout
    • Component
    • Provider
    • Mountable
    • Query
    • Infinite Query
    • Mutation
    • Action
    • Root
    • Base
    • Plugin
  • Methods
    • Validation
    • Loader
    • Context
    • Middleware
    • Loading & error
    • .with
    • Mapper
    • Transformer
    • Stage Methods
  • Core
    • Navigation
    • SSR
    • RSC
    • Request
    • Response
    • Error handling
    • Env
    • Head
    • MDX
    • Assets
    • File upload
    • OpenAPI
    • Query client
    • Events
    • Infer
  • Engine
    • Engine Config
    • Engine Runtime
    • CLI
    • Dev
    • Build
    • Compiler
    • Generator
    • Project MCP
    • Docs MCP
    • Importer
    • Public dir
    • Testing
    • Deploy
    • Bun or Vite
  • Extra
    • SsrStore
    • CookieStore
    • Basic Auth
    • CORS
    • Cache-Control
    • Compress
  • Examples
    • Basic
    • Vite
    • Better Auth
    • Capacitor
    • Expo
  • 1gr14
    • Главная
    • Start0
    • Поддержать
    • Обучение
    • Группа
    • Блог
    • Автор
  • Сообщество
    • Discord
    • Telegram
  • Опенсорс
    • Point0
    • Route0
    • Error0
    • Flat
  • Аккаунт
    • Войти
    • Регистрация
Point0by 1gr14
Создаю опенсорс во славу Господа Иисуса Христа ☦️
С любовью ко всем разработчикам на свете ❤️
Условия использованияПолитика конфиденциальностиСергей Дмитриев 2026 😎

Infer

  • Раздел: Core

On this page

  1. The two you reach for most
  2. Typing a component against its point
  3. Schemas, params, search, body
  4. RouteDefinition
  5. A sibling: InferNavigation
  6. Reference
  7. All Infer keys
  8. Notes on the data family

Every point carries an Infer property whose only job is type extraction: you write typeof somePoint.Infer.<Key> and get the input type, the data type, the route string, the component type, and more, derived from the point itself. Change the point's schema or loader and these types follow automatically.

import { ideaViewQuery } from '@/queries/idea'

// the data the loader returns — no hand-written interface
type IdeaViewData = typeof ideaViewQuery.Infer.QueriedData // => { idea: Idea }

// the raw input the query expects
type IdeaViewInput = typeof ideaViewQuery.Infer.InputRaw // => { id: string }

Infer is on every point — pages, layouts, queries, mutations, actions, roots, bases, plugins — and survives the whole builder chain, so a finalized point still has it. It's free at runtime: Infer is initialized to null, so it exists only in the type system.

GOTCHA — type position only. point.Infer is null at runtime, so accessing any member (e.g. point.Infer.QueriedData) as a value throws — read it only in type position. Always wrap it in typeof.

The two you reach for most

InputRaw — the input a point accepts, pre-validation, with every input source merged (the .input, plus .params / .search / .body where they apply):

const mutation = root.lets
  .mutation()
  .input(z.union([z.object({ id: z.string() }), z.object({ sn: z.number() })]))
  .loader(({ input }) => ({ input }))
  .mutation()

type Input = typeof mutation.Infer.InputRaw // => { id: string } | { sn: number }

Unions are preserved, and a later .input distributes across each member:

// .input(union).input(z.object({ x: z.string() }))
// => { x: string; id: string } | { x: string; sn: number }

QueriedData — the data a query / infinite-query produces, after react-query shapes it (an infinite query wraps it in InfiniteData<…>). This is how you derive a row type from a list query:

export const listAccountsQuery = root.lets
  .query()
  .loader(async ({ request }) => ({
    accounts: await listUserAccounts(request),
  }))
  .query()

// drill into the data to get one item's type
export type AccountsItem = NonNullable<
  typeof listAccountsQuery.Infer.QueriedData.accounts
>[number]

Typing a component against its point

EdgeComponent is the typed React component a mountable point expects, and EdgeProps is the props that component receives. Pull the type out and write the component to match — no manual prop interface:

const page = root.lets
  .page('/:id')
  .loader(({ params }) => ({ x: params.id }))
  .page((props) => <Page {...props} />)

// `Page` is typed from the point: `data` is { x: string }, plus params/search/…
const Page: typeof page.Infer.EdgeComponent = ({ data }) => (
  <div>x={data.x}</div>
)

EdgeComponent / EdgeProps resolve per point kind (page, layout, component, provider). On a point that has no component — a query, a mutation, an action — EdgeComponent is undefined and EdgeProps is never.

The bracket form typeof point.Infer['Key'] is the same as typeof point.Infer.Key; use whichever reads better in a generic position.

Schemas, params, search, body

Each input source exposes its schema and its raw / parsed shapes. "Raw" is the schema's input (pre-validation); "parsed" is its output (post-validation) — they differ when the schema coerces or transforms:

type Params = typeof ideaPage.Infer.ParamsParsed // parsed route params
type Search = typeof ideaPage.Infer.SearchRaw //    raw query-string values
type Body = typeof uploadAction.Infer.BodyParsed // parsed request body

The same *Schema / *Raw / *Parsed triple exists for Params, Search, Body, Headers, and Cookies. See validation for which point type uses which input source.

RouteDefinition

RouteDefinition is the point's final route as a literal type — prefixes from parent bases and roots already compounded in:

const base = root.lets('base', 'base').basePath('/my/prefix').base()
const action = base.lets.action('POST', '/api/my-test/:id') /* … */
type Route = typeof action.Infer.RouteDefinition // => '/my/prefix/api/my-test/:id'

A sibling: InferNavigation

Navigation has its own inference surface — but it is not point.Infer. It comes from createNavigation(...) and types your <Link> / route props against your route table:

export const { Link, navigate, InferNavigation } = createNavigation({
  routes /* … */,
})

export type AppLinkProps = typeof InferNavigation.LinkProps //     embeddable Link props
export type AppNavLinkProps = typeof InferNavigation.NavLinkProps // + active-state classNames
export type AppRouteProps = typeof InferNavigation.RouteProps //    just { route, input }

Same runtime rule: type position only. Full details on Navigation.

Reference

All Infer keys

Every key on typeof point.Infer, in source order. A key that has no matching schema / loader / component on a given point yields its "empty" type (an empty object, undefined, never, or false) rather than an error — so you can read any key on any point.

KeyYields
PointTypethe point's literal kind: 'page' | 'query' | 'mutation' | 'action' | …
LetsReadyPointTypethe kind set via .lets(…) before finalizing, or undefined
Errorthe point's error class (ErrorPoint0 by default, or your own)
RequiredCtxthe context the point requires to run (rarely needed directly)
Ctxthe full accumulated context object
CtxExposedthe subset of Ctx exposed to the client
CtxExposedKeysthe key-union of exposed ctx fields
ServerLoaderOutputraw return type of the server .loader
ClientLoaderOutputraw return type of the .clientLoader
MapperOutputoutput of the point's .mapper
RouteDefinitionthe final route as a literal string
ServerInputSchema / ClientInputSchemathe server / client input schema
IsInputOptionaltrue / false — is the merged input optional?
InputRawthe merged raw (pre-validation) input
InputRawOrUndefinedInputRaw, but undefined when the input is empty
InputRawOrUndefinedOrVoidas above, plus void — for omit-the-arg call sites
ClientInputRaw / ClientInputParsedraw / parsed client input
IsClientInputOptionaltrue / false — is client input optional?
ServerInputRaw / ServerInputParsedmerged raw / parsed server input
IsServerInputOptionaltrue / false — is server input optional?
ParamsSchema / ParamsRaw / ParamsParsedroute-params schema / raw / parsed
SearchSchema / SearchRaw / SearchParsedquery-string schema / raw / parsed
BodySchema / BodyRaw / BodyParsedrequest-body schema / raw / parsed
HeadersSchema / HeadersRaw / HeadersParsedheaders schema / raw / parsed
CookiesSchema / CookiesRaw / CookiesParsedcookies schema / raw / parsed
OuterPropsprops passed into the point's component from outside
InnerPropsprops available inside the component (accumulated)
QueryResultType'query' | 'infiniteQuery' | undefined — the query flavor
Queriesthe point's declared sub-query definitions
UseQueryOptionsthe options type the point's useQuery accepts
UseQueryResultthe result type of the point's useQuery
FetchServerOutputthe server-loader output if present, else never
FetchOutputthe loader output (whichever the point has, server or client)
ServerQueryFiniteData / ClientQueryFiniteDataserver / client finite-query data
ServerQueryInfiniteData / ClientQueryInfiniteDataserver / client infinite-query data
QueriedFiniteData / QueriedInfiniteDatafinal finite / infinite data
ServerQueryData / ClientQueryDataserver / client query data, shaped by result type
QueriedDatathe canonical data key — final query data, react-query-shaped
ServerExecuteResultthe full server-execution result ({ ctx, data, response, redirect, error, … })
EdgeComponentthe typed success component for a mountable point, else undefined
EdgePropsthe props that success component receives, else never

Notes on the data family

For most data extraction, reach for QueriedData (the final, react-query shaped data) or FetchOutput (the raw loader output). The Server* / Client* variants name the output of whichever loader the point uses — a point has exactly one, server or client, never both — and the *FiniteData / *InfiniteData split distinguishes finite from infinite shaping; you rarely need them directly.

There is no Location key on point.Infer — location types belong to Navigation (InferNavigation), not to the point.

НазадEventsДалееEngine Config

Enjoying Point0?

Give it a star on GitHub, ask questions, and follow what's new

Star Point0

A star on GitHub helps more developers find Point0
Star on GitHub

Start0

Point0 integrated into the Start0 SaaS boilerplate — the best way to use it
Explore Start0

YouTube

Tutorials, walkthroughs, and updates
YouTube

Discord

Questions and chat in English
Join Discord

Telegram

News channel and chat in Russian
ChannelChat

Twitter

Posts and updates
Twitter