Overview
All TypeScript types used across the Courier library, organized by category.
Client Types
TypedClient
The main typed client returned by createCaller and createProxyCaller. Provides dot-notation access to groups, .raw for full response, and .with() for per-request options.
type TypedClient<T extends DefinedApi<any>, Raw extends boolean = false> = {
[K in keyof ApiGroups<T>]: GroupClient<ApiGroups<T>[K], Raw>
} & {
raw: TypedClient<T, true>
with(options: WithOptions): TypedClient<T, Raw>
}GroupClient
A group with typed endpoint methods, .raw accessor, and .with(): one method per endpoint of the group, typed from its variables and response, beside these two.
type GroupClient<G, Raw extends boolean = false> = {
// …one method per endpoint of G…
raw: GroupClient<G, true>
with(options: WithOptions): GroupClient<G, Raw>
}WithOptions
Options for .with() — all CallOptions except rawData (controlled via .raw).
type WithOptions = Omit<CallOptions, "rawData">CallerDefaults
Options for createCaller.
type CallerDefaults = {
timeout?: number
headers?: Record<string, string>
context?: Context
onError?: (error: HTTPError) => void | Promise<void>
onSuccess?: (data: unknown) => void | Promise<void>
}ProxyCallerDefaults
Options for createProxyCaller and createProxyQueryCaller.
type ProxyPath = {
http?: string // default: "/api/request"
sse?: string // default: "/api/sse"
ws?: string // no default — throws if WS endpoint invoked without it
}
type ProxyCallerDefaults = {
proxyPath?: ProxyPath
source?: object
timeout?: number
credentials?: RequestCredentials
headers?: Record<string, string>
onError?: (error: HTTPError) => void | Promise<void>
onSuccess?: (data: unknown) => void | Promise<void>
}Endpoint Definition Types
Endpoint Types
An endpoint is an inert descriptor, not a callable. One of three types names it, according to the head it was built from:
import type {
AnyEndpoint, // any of the three, when the kind does not matter
ChannelEndpoint, // ChannelEndpoint<Response, Variables, Send>
HttpEndpoint, // HttpEndpoint<Response, Variables, Kind extends "query" | "mutation">
StreamEndpoint, // StreamEndpoint<Response, Variables>
} from "@noverax/courier/define"Inference Helpers
Read the types back off an endpoint. This is how a caller knows what a method takes and returns:
import type { InferClient } from "@noverax/courier" // InferClient<TApi>: the client createCaller(api) returns
import type {
InferKind, // InferKind<E>: "query" | "mutation" | "stream" | "channel"
InferResponse, // InferResponse<E>: what the endpoint resolves to
InferSend, // InferSend<E>: what a channel accepts from the client
InferVariables, // InferVariables<E>: what the caller must pass
InferVariablesOut, // InferVariablesOut<E>: what its closure receives, once a schema has validated the call
} from "@noverax/courier/define"The clients infer all of this themselves; name a type with these helpers where one is needed elsewhere — a component's props, a test's fixture.
Wire Surfaces
The object .via() hands the closure. Name these to lift a closure out of the
chain into a function of its own:
interface HttpWire {
get(path?: string, variables?: unknown): WireCall
post(path?: string, body?: unknown): WireCall
put(path?: string, body?: unknown): WireCall
patch(path?: string, body?: unknown): WireCall
del(path?: string, variables?: unknown): WireCall
head(path?: string, variables?: unknown): WireCall
}
interface StreamWire {
get(path?: string, variables?: unknown): WireCall
}
interface ChannelWire {
connect(path?: string, variables?: unknown): WireCall
}
type HttpProbe<Variables> = (http: HttpWire, variables: Variables) => WireCall
type StreamProbe<Variables> = (sse: StreamWire, variables: Variables) => WireCall
type ChannelProbe<Variables> = (ws: ChannelWire, variables: Variables) => WireCallimport type { HttpProbe } from "@noverax/courier/define"
const byId: HttpProbe<{ id: string }> = (http, vars) => http.get(":id", vars)
const getById = endpoint.variables<{ id: string }>().via(byId).response<User>()Response Types
HttpResponse
type HttpResponse<T = unknown> = {
status: number // HTTP status code
headers: Headers // Response headers
data: T // Parsed response body
}Options Types
CallOptions
Per-request options passed when calling an endpoint.
type CallOptions<R extends boolean = false> = Omit<RequestInit, "method" | "body"> & {
timeout?: number
responseType?: "json" | "text" | "blob" | "arrayBuffer" | "formData"
onDownloadProgress?: (progress: { percent: number; transferredBytes: number; totalBytes: number }) => void
onUploadProgress?: (progress: UploadProgress) => void
rawData?: R
forwardVariables?: boolean
stream?: boolean
method?: "GET" | "POST"
}headers, signal, credentials and the rest of RequestInit are passed to fetch; method is the verb a call goes to the proxy with, not the endpoint's own.
UploadProgress
type UploadProgress = {
percent: number // 0 to 1
transferredBytes: number
totalBytes: number
}MethodParameters
type MethodParameters<T extends HttpMethod> = T extends "head"
? [url?: string, options?: MethodOptions<T>]
: [url?: string, variables?: Record<string, unknown>, options?: MethodOptions<T>]Source & Config Types
BaseOptions
Core configuration for defineApi().
type BaseOptions = MergeOptions & FetchOptions & {
baseURL?: string
responseType?: ResponseType
responseParser?: (response: Response) => Promise<unknown>
defaultBody?: Record<string, unknown>
defaultQueryParams?: Record<string, unknown>
allowedHeaders?: string[]
bodySerializer?: (data: Record<string, unknown>) => BodyInit
searchParamsSerializer?: SearchParamsSerializer
deduplicate?: boolean
middleware?: Middleware[]
expose?: boolean
boundary?: ProxyBoundary
proxyPath?: ProxyPath
}GroupOptions
type GroupOptions = MergeOptions & {
prefix?: string
}ResponseType
type ResponseType = "json" | "text" | "blob" | "arrayBuffer" | "formData"SearchParamsSerializer
type SearchParamsSerializer = {
stringify: (obj: Record<string, unknown>) => string
parse: (str: string) => Record<string, unknown>
}Context
type Context = {
req?: Request
res?: Response
headers?: Headers
proxyMethod?: "GET" | "POST"
}PathOptions
type PathOptions = (request?: Request) =>
Record<string, boolean | number | string | null | undefined> | undefined
| Promise<Record<string, boolean | number | string | null | undefined> | undefined>Middleware Types
Middleware
type Middleware =
| { name: string; phase: "before"; handler: BeforeHandler }
| { name: string; phase: "after"; handler: AfterHandler }
| { name: string; phase: "wrap"; handler: WrapHandler }defineMiddleware(name, phase, handler) builds one — see Middleware.
MiddlewareContext
type MiddlewareContext = {
source: string
group?: string
method: string
variables?: unknown
headers: Headers
transport?: "http" | "sse" | "ws"
request?: Request
kind?: "query" | "mutation"
carriesSession?: boolean
sessionPartition?: string
signal?: AbortSignal
purpose?: CallPurpose
}
type CallPurpose = "csrf-token"purpose is set on a request the session makes rather than an endpoint's call — "csrf-token" for the double-submit token a write asks for — whose method names no endpoint. See Middleware for each field.
MiddlewareResponse
type MiddlewareResponse = {
status: number
data: unknown
headers: Headers
}NextFn
type NextFn = () => Promise<MiddlewareResponse>React Query Types
type QueryOptions<R, V> = WithVariables<V> &
Omit<UseQueryOptions<R, Error, R, QueryKey>, "queryKey" | "queryFn"> & {
requestOptions?: CallOptions
}
type MutationOptions<R, V> = Omit<
UseMutationOptions<R, Error, MutationVariables<V>>,
"mutationFn"
> & {
requestOptions?: CallOptions
}
type MutationVariables<V> = [V] extends [undefined]
? void
: {} extends V ? void | V : V
type WithVariables<V> = [V] extends [undefined]
? { variables?: undefined }
: {} extends V
? { variables?: V }
: { variables: V }Related
- Type Safety Guide — how type inference works
- createProxyCaller — uses TypedClient and ProxyCallerDefaults
- defineApi — uses BaseOptions
- HttpClient — the runtime that carries out a wire call