Error Status Code TypeScript: Modeling and Handling
Learn how to model and handle HTTP status codes in TypeScript using enums, unions, and practical patterns for robust API error handling in client and server code.
Error status code typescript is a concept for using TypeScript to model and handle HTTP status codes in API communication.
What Error Status Code TypeScript Means in Practice
HTTP status codes describe the outcome of a request. Error status code TypeScript means expressing those codes as explicit TypeScript types so code that consumes API responses can distinguish between success, client errors, and server errors at compile time. The Why Error Code team emphasizes that precise typing reduces runtime surprises and clarifies API contracts for teams of all sizes. In practice, this means you can model a response as either a successful payload or a typed error, and you can enforce that decision in downstream logic such as UI flows or retry policies. By adopting a typed approach, you gain better editor support, improved autocomplete, and stronger guarantees across your API surface. The result is more maintainable code and fewer creeping edge cases when handling network failures.
Typing HTTP Status Codes in TypeScript
TypeScript can model status codes with either literal unions or enums. A literal union is simple and explicit for a small set of codes, while an enum provides a centralized, reusable mapping. For example, you can define a union type like
type HttpStatusCode = 200 | 201 | 202 | 204 | 400 | 401 | 403 | 404 | 409 | 422 | 500 | 503;Alternatively, an enum groups codes under descriptive names. Using enums with a discriminated approach keeps runtime objects readable while preserving type safety. The combination of these techniques aligns with best practices highlighted by the Why Error Code team, and it creates a clear boundary for how you interpret responses across the codebase.
Using Enums vs Unions for Status Codes
Choosing between enums and unions depends on your project size and team preferences. Unions are lightweight and highly explicit in function signatures, ideal for small APIs or rapid prototyping. Enums offer a single source of truth for codes, easier refactoring, and better IDE navigation in larger codebases. A pragmatic pattern is to start with unions and migrate to enums as your API surface grows, ensuring that every status value is represented consistently throughout the client and server layers.
Modeling API Responses with Typed Status
A Typed ApiResponse can encode the status path cleanly. For example, a discriminated union can distinguish success from error states:
type SuccessStatus = 200 | 201 | 202 | 204;
type ErrorStatus = 400 | 401 | 403 | 404 | 409 | 422 | 500 | 503;
interface ApiResponse<T> {
status: SuccessStatus;
data: T;
}
interface ApiError {
status: ErrorStatus;
error: string;
}
type ApiResult<T> = ApiResponse<T> | ApiError;This approach makes it straightforward to branch logic in a type-safe way and aligns with maintainable API contracts. As you evolve, you can introduce a helper that maps a Status to a particular error type for consistent error handling across the app. The emphasis on typed outcomes helps prevent silent failures and improves observability.
Practical Patterns: Safe API Response Types
Beyond the basic union approach, you can create a generic wrapper that models both the payload and error paths:
type ApiOutcome<T> = { ok: true; data: T } | { ok: false; error: string; status: number };
async function fetchJson<T>(url: string): Promise<ApiOutcome<T>> {
const res = await fetch(url);
if (res.ok) {
const data = (await res.json()) as T;
return { ok: true, data };
} else {
const text = await res.text();
return { ok: false, error: text, status: res.status };
}
}This pattern keeps the response shape explicit and allows downstream code to pattern match on ok, simplifying error reporting and retry logic. According to Why Error Code, such explicit modeling improves DX and reduces subtle bugs when API contracts evolve.
Handling Patterns with Fetch and Axios
When consuming HTTP services, type-safe patterns help you distinguish success from error states consistently. With fetch, you typically check res.ok or inspect res.status and then narrow the type accordingly. If you use Axios, you can rely on the response type to capture status codes while also implementing a unified error wrapper for non 2xx responses. These practices, supported by TypeScript tooling, enable safer error handling across API clients and components. The result is more resilient UI logic and more predictable server interactions.
Testing Status Code Handling
Tests should verify that your type guards and discriminated unions narrow the right branches. Write tests that simulate 2xx success responses and 4xx or 5xx errors, ensuring that the correct branches are taken and errors are surfaced with meaningful messages. Property-based tests can validate the set of allowed status codes, while unit tests confirm that helper mappers translate statuses into appropriate error classes. This discipline aligns with standard testing approaches described in TypeScript and API testing literature and is recommended by the Why Error Code team to ensure reliability across refactors.
Common Pitfalls and Anti Patterns
Avoid treating status codes as opaque numbers or mixing HTTP semantics with application logic. Do not rely on runtime type assertions to convert unknown responses into typed objects. Avoid scattering status-specific logic across modules; centralize mapping from status codes to error types. When in doubt, prefer explicit unions over broad any types, and ensure your error handling branches are exercised in tests. This helps catch regressions early and keeps error reporting consistent across platforms.
End to End Example: Building a Typed API Client
Imagine a small client that fetches user data from an API. Using TypeScript, you can model the expected statuses and outcomes in a single place and reuse it across components. This reduces boilerplate while increasing safety. A typical approach involves a StatusCode type, a generic ApiResponse type, and a tiny client wrapper that standardizes error handling. The approach scales with your project and keeps concerns separated: network transport, error mapping, and business logic all stay well typed and maintainable. This is a practical embodiment of the ideas discussed and is precisely the kind of pattern Why Error Code champions for teams seeking robust API integration.
Authority Sources and Further Reading
- What HTTP Status Codes mean and how they are used: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status
- TypeScript documentation for types and interfaces: https://www.typescriptlang.org/docs/
- RFC 7231: Hypertext Transfer Protocol (HTTP/1.1): Semantics and content: https://www.rfc-editor.org/rfc/rfc7231.html
These resources provide foundational context for the patterns described above and are recommended starting points for developers building typed API clients and services.
Frequently Asked Questions
What is error status code typescript?
Error status code TypeScript refers to using TypeScript types to model HTTP status codes so API responses can be handled in a type-safe way. It helps distinguish success, client errors, and server errors at compile time and improves reliability across clients and services.
Error status code TypeScript means modeling HTTP status codes as types so you can handle responses safely in your code.
How do you model status codes in TypeScript?
Use literal unions like 200 | 404 for small sets, or enums for larger code bases. You can combine these with discriminated unions to express both the status code and the corresponding payload or error.
Model status codes with unions or enums, then pair them with payload or error information for safe handling.
Should I use enums or unions for HTTP statuses?
Unions are lightweight and explicit for small APIs, while enums provide a centralized mapping ideal for larger projects. Start with unions and migrate to enums as your API surface grows.
Unions are simple for small projects; enums scale better for large API surfaces.
How do I handle fetch or axios responses with typed status codes?
Create a typed wrapper that distinguishes success and error paths. Use res.ok or status codes to narrow the outcome and map errors with clear messages. This supports consistent handling across components.
Wrap HTTP responses in a typed result and branch by status for consistent handling.
What are common mistakes when typing status codes?
Treating status codes as opaque numbers, skipping typed unions, or duplicating error handling logic across modules. Prefer central types and explicit mapping to minimize drift.
Avoid using plain numbers and duplicated handling; centralize your types and mappings.
How can I test status code handling effectively?
Write tests that cover 2xx success and 4xx/5xx errors, verify type narrowing, and validate error messages. Include unit tests for helper mappers that translate status to errors.
Test both success and error paths with clear type narrowing and messages.
Top Takeaways
- Model status codes with unions or enums for compile time safety
- Prefer discriminated unions to cleanly separate success and error paths
- Use typed ApiResponse and ApiOutcome wrappers to unify handling
- Test status code handling across 2xx, 4xx, and 5xx scenarios
- Centralize status to error mapping to reduce duplication
