try-error Documentation

Migration Guide

Gradually adopt try-error in your existing codebase

Progressive Adoption

try-error is designed for gradual adoption. You can start using it in new code while keeping existing try/catch blocks unchanged.

✅ Safe Migration: try-error works alongside traditional error handling. No need for a big rewrite!

Before and After

Synchronous Operations

❌ Before (try/catch)

Traditional try/catchtypescript
function parseConfig(jsonString: string) {
  try {
    const config = JSON.parse(jsonString);
    return config;
  } catch (error) {
    console.error('Parse failed:', error);
    return null;
  }
}

✅ After (try-error)

try-error Approachtypescript
function parseConfig(jsonString: string) {
  const result = trySync(() => JSON.parse(jsonString));
  if (isTryError(result)) {
    console.error('Parse failed:', result.message);
    return null;
  }
  return result;
}

Asynchronous Operations

❌ Before (try/catch)

Traditional async/awaittypescript
async function fetchUser(id: string) {
  try {
    const response = await fetch(`/api/users/${id}`);
    const user = await response.json();
    return user;
  } catch (error) {
    console.error('Fetch failed:', error);
    throw error;
  }
}

✅ After (try-error)

tryAsync Approachtypescript
async function fetchUser(id: string) {
  const response = await tryAsync(() => 
    fetch(`/api/users/${id}`)
  );
  if (isTryError(response)) {
    console.error('Fetch failed:', response.message);
    return response; // Return the error
  }
  
  const user = await tryAsync(() => response.json());
  return user; // Could be success or error
}

Migration Strategies

1. Start with New Code

Begin using try-error for all new functions and modules. This gives you immediate benefits without touching existing code.

2. Migrate Utility Functions

Convert small utility functions first. These are usually easier to test and have fewer dependencies.

Easy Migration Targettypescript
// Easy migration target
function safeParseInt(value: string) {
  const result = trySync(() => {
    const num = parseInt(value, 10);
    if (isNaN(num)) throw new Error('Not a valid number');
    return num;
  });
  return isTryError(result) ? 0 : result;
}

3. Migrate API Boundaries

Convert functions that interact with external APIs, databases, or file systems. These benefit most from explicit error handling.

4. Gradual Refactoring

When you need to modify existing functions, consider converting them to try-error at the same time.

Interoperability

try-error functions can easily work with traditional try/catch code:

Interoperability Examplestypescript
1// try-error function called from try/catch code
2function legacyFunction() {
3  try {
4    const result = newTryErrorFunction();
5    if (isTryError(result)) {
6      throw new Error(result.message);
7    }
8    return result;
9  } catch (error) {
10    console.error('Legacy error handling:', error);
11    throw error;
12  }
13}
14
15// try/catch function called from try-error code
16async function newFunction() {
17  const result = await tryAsync(() => legacyAsyncFunction());
18  if (isTryError(result)) {
19    console.error('Legacy function failed:', result.message);
20    return null;
21  }
22  return result;
23}

Common Migration Patterns

Error Propagation

Before

Traditional Error Propagationtypescript
async function processData() {
  try {
    const data = await fetchData();
    const processed = await processStep1(data);
    const result = await processStep2(processed);
    return result;
  } catch (error) {
    throw error; // Re-throw
  }
}

After

try-error Error Propagationtypescript
async function processData() {
  const data = await tryAsync(() => fetchData());
  if (isTryError(data)) return data;
  
  const processed = await tryAsync(() => processStep1(data));
  if (isTryError(processed)) return processed;
  
  const result = await tryAsync(() => processStep2(processed));
  return result; // Success or error
}

Default Values

Before

Traditional Default Valuestypescript
function getConfig() {
  try {
    return JSON.parse(configString);
  } catch {
    return defaultConfig;
  }
}

After

try-error Default Valuestypescript
function getConfig() {
  const result = trySync(() => JSON.parse(configString));
  return isTryError(result) ? defaultConfig : result;
}

Testing During Migration

Your existing tests should continue to work. For new try-error code, test both success and error cases:

Testing try-error Functionstypescript
1describe('parseConfig', () => {
2  it('should parse valid JSON', () => {
3    const result = parseConfig('{"key": "value"}');
4    expect(isTryError(result)).toBe(false);
5    if (!isTryError(result)) {
6      expect(result.key).toBe('value');
7    }
8  });
9
10  it('should handle invalid JSON', () => {
11    const result = parseConfig('invalid json');
12    expect(isTryError(result)).toBe(true);
13    if (isTryError(result)) {
14      expect(result.message).toContain('JSON');
15    }
16  });
17});

Next Steps

Core Concepts

Understand the philosophy behind try-error

Learn Concepts →

Examples

See real-world migration examples

View Examples →