Skip to main content

http

HTTP method, status code, content-type, and request/response shape types.

import type {
  HttpMethod, SafeMethod, IdempotentMethod,
  IsSafeMethod, IsIdempotentMethod,
  Informational, Success, Redirection, ClientError, ServerError,
  HttpStatusCode, StatusFamily,
  IsSuccess, IsClientError, IsServerError,
  ContentType,
  HttpRequestShape, HttpResponseShape,
} from '@gentleduck/ttest/http'

Curated HTTP unions and helpers. Constrain client and server APIs to valid methods, status codes, and content types without rolling per-endpoint enums.

HttpMethod

type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTIONS' | 'CONNECT' | 'TRACE'

Every standard method per RFC 9110.

SafeMethod

type SafeMethod = 'GET' | 'HEAD' | 'OPTIONS' | 'TRACE'

Methods that must not modify server state. SafeMethodIdempotentMethodHttpMethod.

IdempotentMethod

type IdempotentMethod = 'GET' | 'HEAD' | 'OPTIONS' | 'TRACE' | 'PUT' | 'DELETE'

Methods whose repeated invocation has the same effect as a single one — safe to retry.

IsSafeMethod

type IsSafeMethod<M extends HttpMethod> = M extends SafeMethod ? true : false
type a = IsSafeMethod<'GET'>   // true
type b = IsSafeMethod<'POST'>  // false

IsIdempotentMethod

type IsIdempotentMethod<M extends HttpMethod> = M extends IdempotentMethod ? true : false
type a = IsIdempotentMethod<'PUT'>   // true
type b = IsIdempotentMethod<'POST'>  // false

Informational

type Informational = 100 | 101 | 102 | 103

1xx status codes.

Success

type Success = 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 226

2xx status codes.

Redirection

type Redirection = 300 | 301 | 302 | 303 | 304 | 305 | 307 | 308

3xx status codes.

ClientError

type ClientError = 400 | 401 | 402 | ... | 451

4xx status codes — every code IANA currently assigns.

ServerError

type ServerError = 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 510 | 511

5xx status codes.

HttpStatusCode

type HttpStatusCode = Informational | Success | Redirection | ClientError | ServerError

Union of every standard status code.

StatusFamily

type StatusFamily<S extends HttpStatusCode>

Grouping label — one of '1xx' | '2xx' | '3xx' | '4xx' | '5xx'.

type a = StatusFamily<200>  // '2xx'
type b = StatusFamily<404>  // '4xx'
type c = StatusFamily<503>  // '5xx'

IsSuccess

type IsSuccess<S extends HttpStatusCode> = S extends Success ? true : false
type a = IsSuccess<200>  // true
type b = IsSuccess<404>  // false

IsClientError

type IsClientError<S extends HttpStatusCode> = S extends ClientError ? true : false

IsServerError

type IsServerError<S extends HttpStatusCode> = S extends ServerError ? true : false
type a = IsServerError<500>  // true
type b = IsServerError<200>  // false

ContentType

type ContentType = 'application/json' | 'text/html' | 'image/png' | ...

Common MIME types. Widen to string if you serve unusual ones.

HttpRequestShape

interface HttpRequestShape<M extends HttpMethod = HttpMethod, Body = unknown> {
  method: M
  headers?: Record<string, string>
  body?: Body
}

Minimal request descriptor — useful in type-safe client builders.

function send<B>(req: HttpRequestShape<'POST', B>): Promise<Response> { /* ... */ }
send({ method: 'POST', body: { id: 1 } })

HttpResponseShape

interface HttpResponseShape<S extends HttpStatusCode = HttpStatusCode, Body = unknown> {
  status: S
  headers?: Record<string, string>
  body: Body
}

Minimal response descriptor. Pair with StatusFamily to type-narrow handlers.

function handle<S extends HttpStatusCode>(res: HttpResponseShape<S>): StatusFamily<S> {
  return (`${Math.floor(res.status / 100)}xx`) as StatusFamily<S>
}

Edge case: every status union is a literal-number set. 404 satisfies HttpStatusCode works; Number('404') satisfies HttpStatusCode does not — call sites typically need as const on numeric literals or an explicit annotation.