Skip to main content

TypeScript Types



interface Manager {
getMiddleware(): Middleware;
cleanup(): void;
init?: (state: State<any>) => void;



interface NetworkError extends Error {
status: number;
response?: Response;


This is a catch-all for errors thrown in fetch functions. It is recommended to try to conform to the NetworkError interface above

type UnknownError = Error & { status?: unknown; response?: unknown };



The bare requirements for an endpoint-type. This is useful for typing function parameters (like hooks), as it is accepting of any correct implementation.

export interface EndpointInterface<
F extends FetchFunction = FetchFunction,
S extends Schema | undefined = Schema | undefined,
M extends true | undefined = true | undefined
> extends EndpointExtraOptions {
(...args: Parameters<F>): InferReturn<F, S>;
key(...args: Parameters<F>): string;
readonly sideEffect?: M;
readonly schema?: S;


function useCache<E extends EndpointInterface>(
endpoint: E,
params: Parameters<E>[0],


An instance of the Endpoint class.

interface EndpointInstance<
F extends FetchFunction = FetchFunction,
S extends Schema | undefined = Schema | undefined,
M extends true | undefined = true | undefined

This is useful to specify types explicitly, instead of implicitly in construction. Being explicit reduces TypeScript computational overhead when inferring types, which is sometimes necessary to avoid tripping the recursion depth limit. This is one of the reasons why there is an eslint rule to explicitly specify return types of methods/functions.

const userDetail: EndpointInstance<FetchFunction<{
id: string;
}>> = new Endpoint(({ id }) => fetch(`/users/${id}`));

class User extends Entity {
static detail<T extends User>(
this: T,
): EndpointInstance<
id: string;
> {
return new Endpoint(({ id }) => fetch(`/users/${id}`), { schema: this });

/** Expected Body payload is a subset of the properties of User
* Expected Response is all the properties of User
static update<T extends User>(
this: T,
): EndpointInstance<
id: string;
// return value is plain object - this is an easy way to extract public members from this class' interface
Omit<T, never>
> {
return new Endpoint(({ id }) => fetch(`/users/${id}`, { method: 'PUT' }), {
schema: this,


Represents a function that does actual fetch. Convenient type to specify only part of the function's type.

export type FetchFunction<A extends readonly any[] = any, R = any> = (
...args: A
) => Promise<R>;

Providing a function type that returns a Promise also works.


export interface RestGenerics {
readonly path: string;
readonly schema?: Schema | undefined;
readonly method?: string;
readonly body?: any;

export type GetEndpoint<
UrlParams = any,
S extends Schema | undefined = Schema | undefined,
> = RestTypeNoBody<UrlParams, S, undefined>;

export type MutateEndpoint<
UrlParams = any,
Body extends BodyInit | Record<string, any> = any,
S extends Schema | undefined = Schema | undefined,
> = RestTypeWithBody<UrlParams, S, true, Body>;