Automated summary
This skill provides robust error handling patterns for TypeScript applications, including custom error classes, a Result type, React error boundaries, and async wrappers.
Strengths
- Covers multiple approaches (error classes, Result, ErrorBoundary, tryCatch) for different contexts.
- Custom error classes include codes and HTTP status codes for better semantics.
- The Result pattern ensures type-safe handling of successes and failures.
- Integrates React error boundaries for frontend applications.
Limitations
- Some patterns (ErrorBoundary) depend on React and class components.
- The Result pattern can add verbosity with type checks.
- Does not cover advanced strategies like retries or fallbacks.
Use this skill to structure error handling in complex TypeScript applications, especially REST APIs and React frontends.
Avoid this skill for simple scripts or projects where lightweight error handling is sufficient.
Security analysis
SafeThe skill provides educational code patterns for error handling in TypeScript. It does not include any destructive operations, obfuscated code, or instructions to execute external commands. The allowed tools are limited to safe file operations.
No concerns found
How this analysis is madeExamples
Create a custom error class NotFoundError that extends AppError with HTTP status code 404 and includes resource name and ID.Implement a Result type in TypeScript and use it for an async function that finds a user by ID, returning success or a NotFoundError.Write a React ErrorBoundary class component that catches errors, logs them, and renders a fallback UI with a role='alert' div showing the error message.name: error-handling-patterns description: Robust error handling patterns for TypeScript applications license: MIT compatibility: typescript 5+, nodejs 18+ allowed-tools: read_file write_file apply_patch search_with_context
Error Handling Patterns
Core Principles
- Fail fast - Detect and report errors early
- Fail safely - Errors shouldn't crash the application
- Fail informatively - Provide actionable error messages
- Recover gracefully - Handle expected failures
Custom Error Classes
// Base application error
export class AppError extends Error {
constructor(
message: string,
public readonly code: string,
public readonly statusCode: number = 500,
public readonly details?: unknown
) {
super(message);
this.name = this.constructor.name;
Error.captureStackTrace(this, this.constructor);
}
toJSON() {
return {
code: this.code,
message: this.message,
...(this.details && { details: this.details }),
};
}
}
// Specific error types
export class ValidationError extends AppError {
constructor(message: string, details?: Record<string, string>) {
super(message, 'VALIDATION_ERROR', 400, details);
}
}
export class NotFoundError extends AppError {
constructor(resource: string, id: string) {
super(`${resource} with id '${id}' not found`, 'NOT_FOUND', 404);
}
}
export class UnauthorizedError extends AppError {
constructor(message = 'Authentication required') {
super(message, 'UNAUTHORIZED', 401);
}
}
export class ForbiddenError extends AppError {
constructor(message = 'Insufficient permissions') {
super(message, 'FORBIDDEN', 403);
}
}
Result Type Pattern
type Result<T, E = Error> =
| { success: true; data: T }
| { success: false; error: E };
// Helper functions
function ok<T>(data: T): Result<T, never> {
return { success: true, data };
}
function err<E>(error: E): Result<never, E> {
return { success: false, error };
}
// Usage
async function findUser(id: string): Promise<Result<User, NotFoundError>> {
const user = await db.users.findUnique({ where: { id } });
if (!user) {
return err(new NotFoundError('User', id));
}
return ok(user);
}
// Consuming
const result = await findUser('123');
if (!result.success) {
console.error(result.error.message);
return;
}
const user = result.data; // Type-safe User
Error Boundaries (React)
import { Component, ErrorInfo, ReactNode } from 'react';
interface Props {
children: ReactNode;
fallback?: ReactNode;
onError?: (error: Error, info: ErrorInfo) => void;
}
interface State {
hasError: boolean;
error: Error | null;
}
export class ErrorBoundary extends Component<Props, State> {
state: State = { hasError: false, error: null };
static getDerivedStateFromError(error: Error): State {
return { hasError: true, error };
}
componentDidCatch(error: Error, info: ErrorInfo) {
this.props.onError?.(error, info);
}
render() {
if (this.state.hasError) {
return this.props.fallback ?? (
<div role="alert">
<h2>Something went wrong</h2>
<pre>{this.state.error?.message}</pre>
</div>
);
}
return this.props.children;
}
}
Async Error Handling
// Wrapper for async functions
function tryCatch<T>(
promise: Promise<T>
): Promise<[null, T] | [Error, null]> {
return promise
.then((data) => [null, data] as [null, T])
.catch((error) => [error as Error, null]);
}
// Usage
const [error, user] = await tryCatch(fetchUser(id));
if (error) {
handleError(error);
return;
}
// user is guaranteed to be defined here
// Multiple operations
async function processOrder(orderId: string) {
const [orderError, order] = await tryCatch(getOrder(orderId));
if (orderError) return err(orderError);
const [paymentError] = await tryCatch(processPayment(order));
if (paymentError) {
await tryCatch(rollbackOrder(order));
return err(paymentError);
}
return ok(order);
}
Retry Pattern
interface RetryOptions {
maxAttempts: number;
delayMs: number;
backoff?: 'linear' | 'exponential';
shouldRetry?: (error: Error) => boolean;
}
async function withRetry<T>(
fn: () => Promise<T>,
options: RetryOptions
): Promise<T> {
const { maxAttempts, delayMs, backoff = 'exponential', shouldRetry } = options;
let lastError: Error;
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
try {
return await fn();
} catch (error) {
lastError = error as Error;
if (shouldRetry && !shouldRetry(lastError)) {
throw lastError;
}
if (attempt < maxAttempts) {
const delay = backoff === 'exponential'
? delayMs * Math.pow(2, attempt - 1)
: delayMs * attempt;
await sleep(delay);
}
}
}
throw lastError!;
}
// Usage
const data = await withRetry(() => fetchFromAPI(), {
maxAttempts: 3,
delayMs: 1000,
shouldRetry: (err) => err.message.includes('timeout'),
});
Validation Errors
import { z } from 'zod';
function validateInput<T>(schema: z.ZodSchema<T>, input: unknown): Result<T, ValidationError> {
const result = schema.safeParse(input);
if (!result.success) {
const details = result.error.flatten().fieldErrors;
return err(new ValidationError('Invalid input', details));
}
return ok(result.data);
}
// Usage
const userSchema = z.object({
email: z.string().email(),
age: z.number().min(18),
});
const result = validateInput(userSchema, req.body);
if (!result.success) {
return res.status(400).json(result.error.toJSON());
}
Logging Errors
interface ErrorContext {
userId?: string;
requestId?: string;
path?: string;
[key: string]: unknown;
}
function logError(error: Error, context: ErrorContext = {}) {
const payload = {
timestamp: new Date().toISOString(),
name: error.name,
message: error.message,
stack: error.stack,
...(error instanceof AppError && { code: error.code }),
...context,
};
console.error(JSON.stringify(payload));
// Send to error tracking service
if (process.env.NODE_ENV === 'production') {
// Sentry.captureException(error, { extra: context });
}
}
Best Practices
- Create specific error types for different failure modes
- Use Result types for expected failures (validation, not found)
- Throw errors for unexpected failures (bugs, system errors)
- Include context in error messages for debugging
- Log at boundaries - API handlers, event processors
- Validate at boundaries - external input, API responses
- Implement retry for transient failures
- Use error boundaries in React for graceful degradation
From the file to a first result
The download contains exactly the content displayed on this page. This copy may differ from the latest version in the source repository.
View the source and supporting filesThis download contains SKILL.md only. Any scripts, references, templates and dependencies are not included. Get the required files from the source, preserving their directory structure, before continuing.
1. Download the file
Download SKILL.mdFrom the root of a test project, save the file as .skill-downloads/typescript-error-handling-patterns-mma3jrtp/SKILL.md, or use the command below. This folder is for inspecting the skill before installation.
Command for macOS/Linux or WSL: requires a POSIX shell and curl. On Windows without WSL, use the download button and create the folder manually.
mkdir -p '.skill-downloads/typescript-error-handling-patterns-mma3jrtp' && curl --fail --show-error --location 'https://skills-guides.com/api/skills/typescript-error-handling-patterns-mma3jrtp/download' --output '.skill-downloads/typescript-error-handling-patterns-mma3jrtp/SKILL.md.part' && mv '.skill-downloads/typescript-error-handling-patterns-mma3jrtp/SKILL.md.part' '.skill-downloads/typescript-error-handling-patterns-mma3jrtp/SKILL.md'2. Check prerequisites
Read SKILL.md before using it. If it references scripts or external services, inspect them and prepare the required access in your test environment.
Environment declared by the author: typescript 5+, nodejs 18+
Tools declared by the author (check availability in your agent): read_file write_file apply_patch search_with_context
No recognized prerequisites section in this file. This does not mean it is self-contained: libraries, tools and access requirements may be mentioned elsewhere in the content or source repository.
The platforms on this page are catalog indications. The paths below follow tool documentation; they do not prove this skill has been run in those tools. No minimum tool version is confirmed for this listing.
3. Load the skill
After inspection, copy the complete folder into your project using one of the commands below, then open a new tool session. The command stops if a folder with the same name already exists: compare the files before replacing it.
Claude Code
test -f '.skill-downloads/typescript-error-handling-patterns-mma3jrtp/SKILL.md' && test -s '.skill-downloads/typescript-error-handling-patterns-mma3jrtp/SKILL.md' && mkdir -p '.claude/skills' && test ! -e '.claude/skills/error-handling-patterns' && cp -R '.skill-downloads/typescript-error-handling-patterns-mma3jrtp' '.claude/skills/error-handling-patterns'Cursor
test -f '.skill-downloads/typescript-error-handling-patterns-mma3jrtp/SKILL.md' && test -s '.skill-downloads/typescript-error-handling-patterns-mma3jrtp/SKILL.md' && mkdir -p '.cursor/skills' && test ! -e '.cursor/skills/error-handling-patterns' && cp -R '.skill-downloads/typescript-error-handling-patterns-mma3jrtp' '.cursor/skills/error-handling-patterns'Codex
test -f '.skill-downloads/typescript-error-handling-patterns-mma3jrtp/SKILL.md' && test -s '.skill-downloads/typescript-error-handling-patterns-mma3jrtp/SKILL.md' && mkdir -p '.agents/skills' && test ! -e '.agents/skills/error-handling-patterns' && cp -R '.skill-downloads/typescript-error-handling-patterns-mma3jrtp' '.agents/skills/error-handling-patterns'OpenSkills
OpenSkills must already be installed. The local install/read procedure is checked with OpenSkills 1.5.0, which requires Node.js ≥ 20.6.0. Catalog slugs are not resolved automatically.
Official OpenSkills installationopenskills install './.skill-downloads/typescript-error-handling-patterns-mma3jrtp'openskills read 'typescript-error-handling-patterns-mma3jrtp'Reading should display the installed file content and its base directory. It does not run the skill or install its dependencies.
For an agent that reads AGENTS.md, then sync the index. This command changes AGENTS.md: review the diff before using it.
openskills syncManual method or another tool: attach SKILL.md to a conversation, or open it in an agent that can read files. Include any required supporting resources. No universal folder is recognized by every tool.
4. Try a first task
Use a short, synthetic input: an API endpoint, a small document or an interface brief. In a new conversation, attach the file or give the agent its path, then adapt this request:
Read .skill-downloads/typescript-error-handling-patterns-mma3jrtp/SKILL.md and apply its instructions to this example: [describe a test input]. Identify any missing files, dependencies or access. Produce the result requested by the skill without inventing data or running unreviewed scripts.Expected result: output matching the skill instructions, or a precise list of missing prerequisites. A read confirmation alone does not validate a first use. If an external resource is unavailable, that path remains untested.
React Hook Form Best Practices
Development
Master React Hook Form: avoid anti-patterns, manage subscriptions, and handle reset, dirty state, and controlled inputs correctly.
Emotion to Mantine Migration
Development
Migrate Emotion styled-components to Mantine components with style props and CSS modules. Use when converting .styled.tsx files or removing @emotion imports.
Scope Creep Detector
Development
Analyzes git diffs against a stated intent to detect scope creep, unrelated files, broad PRs, and oversized changes, then suggests keep, split, or justify actions.