try-error Documentation

Integration Guides

Learn how to integrate try-error with popular frameworks, libraries, and tools

Express.js Integration

Integrate try-error with Express.js for consistent error handling across your API routes.

Express.js Error Handling Middlewaretypescript
1import express from 'express';
2import { tryAsync, isTryError } from 'try-error';
3
4const app = express();
5
6// Error handling middleware
7const handleTryError = (req: express.Request, res: express.Response, next: express.NextFunction) => {
8  return async (handler: (req: express.Request, res: express.Response) => Promise<any>) => {
9    const result = await tryAsync(() => handler(req, res));
10    
11    if (isTryError(result)) {
12      console.error('Route error:', result);
13      
14      // Map error types to HTTP status codes
15      const statusCode = getStatusCodeFromError(result);
16      
17      res.status(statusCode).json({
18        error: {
19          message: result.message,
20          type: result.type,
21          ...(process.env.NODE_ENV === 'development' && {
22            stack: result.stack,
23            context: result.context
24          })
25        }
26      });
27    }
28  };
29};
30
31function getStatusCodeFromError(error: TryError): number {
32  switch (error.type) {
33    case 'ValidationError': return 400;
34    case 'AuthenticationError': return 401;
35    case 'AuthorizationError': return 403;
36    case 'NotFoundError': return 404;
37    case 'ConflictError': return 409;
38    case 'RateLimitError': return 429;
39    default: return 500;
40  }
41}
42
43// Usage in routes
44app.get('/users/:id', handleTryError(async (req, res) => {
45  const userId = req.params.id;
46  
47  if (!userId) {
48    throw new Error('User ID is required');
49  }
50  
51  const user = await fetchUser(userId);
52  res.json(user);
53}));
54
55app.post('/users', handleTryError(async (req, res) => {
56  const userData = req.body;
57  
58  // Validation
59  const validationResult = validateUserData(userData);
60  if (isTryError(validationResult)) {
61    throw validationResult;
62  }
63  
64  const newUser = await createUser(userData);
65  res.status(201).json(newUser);
66}));

Next.js Integration

Use try-error in Next.js API routes and server components for robust error handling.

API Routes

Next.js API Route with try-errortypescript
1// pages/api/users/[id].ts
2import { NextApiRequest, NextApiResponse } from 'next';
3import { tryAsync, isTryError } from 'try-error';
4
5export default async function handler(req: NextApiRequest, res: NextApiResponse) {
6  if (req.method !== 'GET') {
7    return res.status(405).json({ error: 'Method not allowed' });
8  }
9
10  const result = await tryAsync(async () => {
11    const { id } = req.query;
12    
13    if (typeof id !== 'string') {
14      throw new Error('Invalid user ID');
15    }
16    
17    return await fetchUser(id);
18  });
19
20  if (isTryError(result)) {
21    console.error('API Error:', result);
22    
23    const statusCode = result.message.includes('Invalid') ? 400 : 500;
24    return res.status(statusCode).json({
25      error: result.message,
26      ...(process.env.NODE_ENV === 'development' && {
27        details: result.context
28      })
29    });
30  }
31
32  res.json(result);
33}

App Router (Next.js 13+)

Next.js App Router with try-errortypescript
1// app/api/users/[id]/route.ts
2import { NextRequest, NextResponse } from 'next/server';
3import { tryAsync, isTryError } from 'try-error';
4
5export async function GET(
6  request: NextRequest,
7  { params }: { params: { id: string } }
8) {
9  const result = await tryAsync(async () => {
10    const user = await fetchUser(params.id);
11    return user;
12  });
13
14  if (isTryError(result)) {
15    return NextResponse.json(
16      { error: result.message },
17      { status: 500 }
18    );
19  }
20
21  return NextResponse.json(result);
22}
23
24// Server Component
25export default async function UserPage({ params }: { params: { id: string } }) {
26  const result = await tryAsync(() => fetchUser(params.id));
27  
28  if (isTryError(result)) {
29    return (
30      <div className="error-container">
31        <h1>Error Loading User</h1>
32        <p>{result.message}</p>
33      </div>
34    );
35  }
36  
37  return (
38    <div>
39      <h1>{result.name}</h1>
40      <p>{result.email}</p>
41    </div>
42  );
43}

Prisma Integration

Wrap Prisma operations with try-error for consistent database error handling.

Prisma Service with try-errortypescript
1import { PrismaClient, Prisma } from '@prisma/client';
2import { tryAsync, isTryError, createTryError } from 'try-error';
3
4const prisma = new PrismaClient();
5
6// Database service with try-error
7export class UserService {
8  static async findById(id: string) {
9    return tryAsync(async () => {
10      const user = await prisma.user.findUnique({
11        where: { id },
12        include: { posts: true }
13      });
14      
15      if (!user) {
16        throw createTryError('NotFoundError', `User with id ${id} not found`, {
17          userId: id
18        });
19      }
20      
21      return user;
22    });
23  }
24
25  static async create(data: Prisma.UserCreateInput) {
26    return tryAsync(async () => {
27      try {
28        return await prisma.user.create({ data });
29      } catch (error) {
30        if (error instanceof Prisma.PrismaClientKnownRequestError) {
31          if (error.code === 'P2002') {
32            throw createTryError('ConflictError', 'User already exists', {
33              field: error.meta?.target,
34              originalError: error
35            });
36          }
37        }
38        throw error;
39      }
40    });
41  }
42
43  static async update(id: string, data: Prisma.UserUpdateInput) {
44    return tryAsync(async () => {
45      try {
46        return await prisma.user.update({
47          where: { id },
48          data
49        });
50      } catch (error) {
51        if (error instanceof Prisma.PrismaClientKnownRequestError) {
52          if (error.code === 'P2025') {
53            throw createTryError('NotFoundError', `User with id ${id} not found`, {
54              userId: id
55            });
56          }
57        }
58        throw error;
59      }
60    });
61  }
62
63  static async delete(id: string) {
64    return tryAsync(async () => {
65      try {
66        await prisma.user.delete({ where: { id } });
67      } catch (error) {
68        if (error instanceof Prisma.PrismaClientKnownRequestError) {
69          if (error.code === 'P2025') {
70            throw createTryError('NotFoundError', `User with id ${id} not found`, {
71              userId: id
72            });
73          }
74        }
75        throw error;
76      }
77    });
78  }
79}
80
81// Usage
82async function handleUserRequest(userId: string) {
83  const userResult = await UserService.findById(userId);
84  
85  if (isTryError(userResult)) {
86    if (userResult.type === 'NotFoundError') {
87      return { status: 404, error: 'User not found' };
88    }
89    return { status: 500, error: 'Database error' };
90  }
91  
92  return { status: 200, data: userResult };
93}

Zod Integration

Combine try-error with Zod for robust input validation and error handling.

Zod Validation with try-errortypescript
1import { z } from 'zod';
2import { trySync, isTryError, createTryError } from 'try-error';
3
4// Schema definitions
5const UserSchema = z.object({
6  name: z.string().min(2, 'Name must be at least 2 characters'),
7  email: z.string().email('Invalid email format'),
8  age: z.number().min(18, 'Must be at least 18 years old').optional(),
9});
10
11const CreateUserSchema = UserSchema.extend({
12  password: z.string().min(8, 'Password must be at least 8 characters'),
13});
14
15// Validation helper
16function validateWithTryError<T>(schema: z.ZodSchema<T>, data: unknown) {
17  return trySync(() => {
18    const result = schema.safeParse(data);
19    
20    if (!result.success) {
21      const errors = result.error.errors.map(err => ({
22        field: err.path.join('.'),
23        message: err.message,
24        code: err.code
25      }));
26      
27      throw createTryError('ValidationError', 'Validation failed', {
28        validationErrors: errors,
29        invalidData: data
30      });
31    }
32    
33    return result.data;
34  });
35}
36
37// Usage in API routes
38export async function createUser(userData: unknown) {
39  // Validate input
40  const validationResult = validateWithTryError(CreateUserSchema, userData);
41  
42  if (isTryError(validationResult)) {
43    return validationResult; // Return validation error
44  }
45  
46  // Proceed with validated data
47  const result = await tryAsync(async () => {
48    const hashedPassword = await hashPassword(validationResult.password);
49    
50    return await UserService.create({
51      name: validationResult.name,
52      email: validationResult.email,
53      age: validationResult.age,
54      password: hashedPassword
55    });
56  });
57  
58  return result;
59}
60
61// Express middleware for validation
62function validateBody<T>(schema: z.ZodSchema<T>) {
63  return (req: express.Request, res: express.Response, next: express.NextFunction) => {
64    const validationResult = validateWithTryError(schema, req.body);
65    
66    if (isTryError(validationResult)) {
67      return res.status(400).json({
68        error: 'Validation failed',
69        details: validationResult.context?.validationErrors
70      });
71    }
72    
73    req.body = validationResult;
74    next();
75  };
76}

Jest Testing Integration

Test your try-error implementations effectively with Jest custom matchers and utilities.

Custom Jest Matchers

Jest Custom Matchers for try-errortypescript
1// jest-setup.ts
2import { isTryError } from 'try-error';
3
4declare global {
5  namespace jest {
6    interface Matchers<R> {
7      toBeTryError(): R;
8      toBeTrySuccess(): R;
9      toHaveErrorType(type: string): R;
10      toHaveErrorMessage(message: string | RegExp): R;
11    }
12  }
13}
14
15expect.extend({
16  toBeTryError(received) {
17    const pass = isTryError(received);
18    
19    if (pass) {
20      return {
21        message: () => `expected ${received} not to be a TryError`,
22        pass: true,
23      };
24    } else {
25      return {
26        message: () => `expected ${received} to be a TryError`,
27        pass: false,
28      };
29    }
30  },
31
32  toBeTrySuccess(received) {
33    const pass = !isTryError(received);
34    
35    if (pass) {
36      return {
37        message: () => `expected ${received} not to be a successful result`,
38        pass: true,
39      };
40    } else {
41      return {
42        message: () => `expected ${received} to be a successful result`,
43        pass: false,
44      };
45    }
46  },
47
48  toHaveErrorType(received, expectedType) {
49    if (!isTryError(received)) {
50      return {
51        message: () => `expected ${received} to be a TryError`,
52        pass: false,
53      };
54    }
55    
56    const pass = received.type === expectedType;
57    
58    if (pass) {
59      return {
60        message: () => `expected error type not to be ${expectedType}`,
61        pass: true,
62      };
63    } else {
64      return {
65        message: () => `expected error type ${received.type} to be ${expectedType}`,
66        pass: false,
67      };
68    }
69  },
70
71  toHaveErrorMessage(received, expectedMessage) {
72    if (!isTryError(received)) {
73      return {
74        message: () => `expected ${received} to be a TryError`,
75        pass: false,
76      };
77    }
78    
79    const pass = typeof expectedMessage === 'string' 
80      ? received.message === expectedMessage
81      : expectedMessage.test(received.message);
82    
83    if (pass) {
84      return {
85        message: () => `expected error message not to match ${expectedMessage}`,
86        pass: true,
87      };
88    } else {
89      return {
90        message: () => `expected error message "${received.message}" to match ${expectedMessage}`,
91        pass: false,
92      };
93    }
94  },
95});

Test Examples

Jest Tests with try-errortypescript
1// user.test.ts
2import { UserService } from './user-service';
3
4describe('UserService', () => {
5  describe('findById', () => {
6    it('should return user when found', async () => {
7      const result = await UserService.findById('existing-id');
8      
9      expect(result).toBeTrySuccess();
10      expect(result).toEqual(expect.objectContaining({
11        id: 'existing-id',
12        name: expect.any(String),
13        email: expect.any(String)
14      }));
15    });
16
17    it('should return NotFoundError when user does not exist', async () => {
18      const result = await UserService.findById('non-existent-id');
19      
20      expect(result).toBeTryError();
21      expect(result).toHaveErrorType('NotFoundError');
22      expect(result).toHaveErrorMessage(/User with id .* not found/);
23    });
24  });
25
26  describe('create', () => {
27    it('should create user successfully', async () => {
28      const userData = {
29        name: 'John Doe',
30        email: 'john@example.com'
31      };
32      
33      const result = await UserService.create(userData);
34      
35      expect(result).toBeTrySuccess();
36      expect(result).toEqual(expect.objectContaining(userData));
37    });
38
39    it('should return ConflictError for duplicate email', async () => {
40      const userData = {
41        name: 'Jane Doe',
42        email: 'existing@example.com'
43      };
44      
45      const result = await UserService.create(userData);
46      
47      expect(result).toBeTryError();
48      expect(result).toHaveErrorType('ConflictError');
49      expect(result).toHaveErrorMessage('User already exists');
50    });
51  });
52});
53
54// Testing validation
55describe('User validation', () => {
56  it('should validate user data successfully', () => {
57    const validData = {
58      name: 'John Doe',
59      email: 'john@example.com',
60      age: 25
61    };
62    
63    const result = validateWithTryError(UserSchema, validData);
64    
65    expect(result).toBeTrySuccess();
66    expect(result).toEqual(validData);
67  });
68
69  it('should return validation error for invalid data', () => {
70    const invalidData = {
71      name: 'J', // Too short
72      email: 'invalid-email',
73      age: 15 // Too young
74    };
75    
76    const result = validateWithTryError(UserSchema, invalidData);
77    
78    expect(result).toBeTryError();
79    expect(result).toHaveErrorType('ValidationError');
80    expect(result.context?.validationErrors).toHaveLength(3);
81  });
82});

TypeScript Configuration

Optimize your TypeScript configuration for the best try-error experience.

Recommended tsconfig.jsonjson
1{
2  "compilerOptions": {
3    "strict": true,
4    "exactOptionalPropertyTypes": true,
5    "noUncheckedIndexedAccess": true,
6    "noImplicitReturns": true,
7    "noFallthroughCasesInSwitch": true,
8    "noImplicitOverride": true,
9    "allowUnusedLabels": false,
10    "allowUnreachableCode": false,
11    
12    // For better error handling
13    "useUnknownInCatchVariables": true,
14    
15    // Module resolution
16    "moduleResolution": "node",
17    "esModuleInterop": true,
18    "allowSyntheticDefaultImports": true,
19    
20    // Path mapping for cleaner imports
21    "baseUrl": ".",
22    "paths": {
23      "@/*": ["src/*"],
24      "@/types/*": ["src/types/*"],
25      "@/utils/*": ["src/utils/*"]
26    }
27  },
28  "include": [
29    "src/**/*",
30    "tests/**/*",
31    "jest-setup.ts"
32  ]
33}

Key Configuration Benefits

  • strict: true - Enables all strict type checking
  • exactOptionalPropertyTypes: true - Better optional property handling
  • noUncheckedIndexedAccess: true - Safer array/object access
  • useUnknownInCatchVariables: true - Safer error handling in catch blocks

Related Pages

Migration Guides

Step-by-step migration from other error handling approaches

View Migration Guides →

Best Practices

Learn recommended patterns and performance tips

View Best Practices →

React Integration

Specific guidance for React applications

View React Guide →