Create Instance
createExpectStatus returns a configured expectStatus function. Set up defaults, error logging, and message extraction once — every call site inherits them.
Basic setup
Section titled “Basic setup”import { createExpectStatus } from 'expect-status'
export const expectStatus = createExpectStatus({ fallbackMessage: 'Something went wrong.', defaults: { 401: 'Please sign in.', 403: 'You do not have permission.', '5xx': 'Service is temporarily unavailable.', }, onError: (err, res) => { Sentry.captureException(err, { extra: { status: res.status } }) }, onSuccess: (res) => { analytics.track('api_success', { status: res.status }) },})Now use expectStatus everywhere — per-call dispatch shadows these defaults when needed:
const org = await expectStatus(201, api.createOrg({ body: data }), { 409: ({ orgId }) => redirect(`/org/${orgId}`),})Defaults
Section titled “Defaults”Instance defaults use the same flat dispatch as per-call — strings are messages, functions are handlers:
const expectStatus = createExpectStatus({ defaults: { 401: 'Please sign in.', 403: 'You do not have permission.', 429: (body) => { throw new Error('Too many requests. Please slow down.') }, '5xx': 'Service is temporarily unavailable.', },})Per-call entries always shadow defaults at the same key.
Custom groups
Section titled “Custom groups”Define named status groups, then use them as expected status arguments or dispatch keys:
const expectStatus = createExpectStatus({ groups: { auth: [401, 403], retryable: [408, 429, 500, 502, 503, 504], },})
// As expected statusawait expectStatus('!auth', response)
// As dispatch keysawait expectStatus(200, response, { auth: () => redirect('/sign-in'), retryable: 'Please try again shortly.',})Custom error class
Section titled “Custom error class”Replace the default ExpectStatusError with your own:
class RequestError extends Error { constructor(message: string, public status: number, public body: unknown) { super(message) this.name = 'RequestError' }}
const expectStatus = createExpectStatus({ errorFactory: (message, response) => new RequestError(message, response.status, response.body),})Multiple instances
Section titled “Multiple instances”Create separate instances for different contexts:
export const publicApi = createExpectStatus({ defaults: { 401: 'Please sign in to access the public API.' },})
export const adminApi = createExpectStatus({ defaults: { 401: 'Admin access required.', 403: 'You do not have admin privileges.', },})All options
Section titled “All options”| Option | Type | Description |
|---|---|---|
defaults | flat dispatch object | Instance-wide handlers and messages |
groups | Record<string, number[]> | Named status groups |
errorFactory | (msg, response) => Error | Custom error constructor |
extractMessage | (body) => string | undefined | Custom message extraction |
fallbackMessage | string | Last-resort error message |
onError | (err, response) => void | Error observability hook |
onSuccess | (response) => void | Success observability hook |
statusField | string | Custom status field name (default: 'status') |
bodyField | string | Custom body field name (default: 'body') |
Next steps
Section titled “Next steps”- Observability Hooks — onError and onSuccess in detail
- Message Extraction — customize error message extraction
- Custom Envelope — statusField and bodyField