Skip to content

With Native Fetch

The recommended approach is to pass a fetcher to your instance and use the method helpers (.get(), .post(), etc.):

import { createExpectStatus } from "expect-status";
const api = createExpectStatus<{
401: { message: string };
403: { message: string };
422: { fieldErrors: Record<string, string> };
}>({
fetcher: (url, init) =>
fetch(`https://api.example.com${url}`, {
...init,
headers: { ...init?.headers, Authorization: `Bearer ${getToken()}` },
}),
defaults: {
401: ({ message }) => router.push("/login"),
403: "You do not have permission.",
"5xx": "Service unavailable.",
},
onError: (err) => Sentry.captureException(err),
});
const user = await api.get<User>("/users/me", 200);
const org = await api.post<Organisation, CreateOrgInput>(
"/organisations",
data,
201,
{
409: ({ organisationId }) => router.push(`/org/${organisationId}`),
422: ({ fieldErrors }) => setFieldErrors(fieldErrors),
},
);
const updated = await api.put<Organisation, UpdateOrgInput>(
"/organisations/123",
changes,
200,
);
await api.patch<void, { name: string }>(
"/organisations/123",
{ name: "New" },
204,
);
await api.delete("/organisations/123", 204);

Pass headers, signal, or any RequestInit key alongside dispatch:

const flags = await api.get<FeatureFlags>("/feature-flags", 200, {
headers: { "X-Region": "eu-west-1" },
signal: abortController.signal,
recover: () => DEFAULT_FLAGS,
});
const result = await api.get<User>("/users/me", 200, { throws: false });
if (result.ok) {
renderUser(result.data);
} else {
showError(result.error.message);
}

You can also pass fetch() calls directly to expectStatus:

import { createExpectStatus, adapters } from "expect-status";
const expectStatus = createExpectStatus({
adapter: adapters.fetch,
defaults: { 401: "Please sign in.", "5xx": "Service unavailable." },
});
const user = await expectStatus(200, fetch("/api/users/1"));