Catches errors and rejected promises, returns tuple
npm install do-try-tupleCatches errors and rejected promises, returns tuple with error and value.
- Installation
- Usage
- Async Usage
- API
- doTry function
- safe promise wrapper
- Failure type
- Success type
- ErrValueTuple type
- failure and success factory functions
- isFailure and isSuccess type guards
- Using doTry().then()
``bash`
npm install do-try-tuple
`typescript
import doTry from 'do-try-tuple';
function div(a: number, b: number): number {
if (b !== 0) return a / b;
if (a !== 0) throw new Error(Division by Zero);
throw new Error('Indeterminate Form');
}
const [isDivOk, errX, x] = doTry(() => div(4, 2));
if (isDivOk) {
const doubleX = x * 2;
console.log('doubleX:', doubleX);
}
`
`typescript
import doTry from 'do-try-tuple';
const [areUsersFetched, error, users] = await doTry(() => fetchUsers());
if (!areUsersFetched) {
console.error('Failed to fetch users:', error);
} else {
console.log('Users:', users);
}
`
or
`typescript
import { safe } from 'do-try-tuple';
const [areUsersFetched, error, users] = await safe(fetchUsers());
if (!areUsersFetched) {
console.error('Failed to fetch users:', error);
} else {
console.log('Users:', users);
}
`
The library exports:
- doTry function (default export)safe
- promise wrapper to make it resolving to ErrValueTupleFailure
- , Success and ErrValueTuple typesfailure
- and success factory functionsisFailure
- and isSuccess type guards
takes a function that may throw an error or return a promise that may be rejected.
`typescript`
function (fn: () => never): readonly [false, unknown, never];
function (fn: () => Promise
function
function
is a function that wraps a promise and makes it resolving to ErrValueTuple:
`typescript`
function safe
It could be useful when you need to handle the promise rejection synchronously:
`typescript
import { safe } from 'do-try-tuple';
const [areUsersFatched, error, users] = await safe(fetchUsers());
`
is a tuple representing the error case:
`typescript`
export type Failure
The library respects the same motivation as caused introduction
useUnknownInCatchVariables
compiler option in TypeScript:
is a tuple representing the success case:
`typescript`
export type Success
is a union of Failure and Success.
`typescript`
export type ErrValueTuple
These functions allow to create ErrValueTuple instances:
`typescript`
export function failure
export function success
It could be useful in tests:
`typescript
import { success, failure } from 'do-try-tuple';
test('div', () => {
expect(doTry(() => div(4, 2))).toEqual(success(2));
expect(doTry(() => div(4, 0))).toEqual(failure(new Error('Division by Zero')));
expect(doTry(() => div(0, 0))).toEqual(failure(new Error('Indeterminate Form')));
});
`
These functions allow to check if the value is Failure or Success:
`typescript`
export function isFailure(value: ErrValueTuple
export function isSuccess(value: ErrValueTuple
It allows to check the result and narrow the type without destructuring:
`typescript
class DivError extends Error {
constructor(message: string) {
super(message);
this.name = 'DivError';
}
}
function divWithTypeError(a: number, b: number): ErrValueTuple
const result = doTry(() => div(a, b));
if (isSuccess(result)) return result;
return failure(new DivError('Failed to divide'));
}
`
You can map the result of doTry applied to function returning a promise using then method:
`typescript
import doTry from 'do-try-tuple';
const [error, users] = await doTry(() => fetchUsers()).then(
([err, users]) => [err && new SomeCustomError(err), users] as const,
);
`
However, consider that functions returning promises can throw error synchronously:
`typescript`
const fetchUsers = (): Promise
if (Math.random() < 0.5) throw new Error('Failed to fetch users');
return Promise.resolve(['Alice', 'Bob', 'Charlie']);
};
So, the doTry in this case returns an ErrValueTuple synchronously, and thethen
attempt to call method on it will throw an error:TypeError: doTry(...).then is not a function.
To handle this case, just add async keyword before fn argument:
`typescript`
const [error, users] = await doTry(async () => fetchUsers()).then(
([err, users]) => [err && new SomeCustomError(err), users] as const,
);
So, use
`typescript`
// CORRECT _____
const [err, value] = await doTry(async () => someFn(...))
.then(([err, value]) => {
// handle err and value
});
instead of
`typescript`
// WRONG ___________
const [err, value] = await doTry(/ async /() => someFn(...))
.then(([err, value]) => {
// handle err and value
});
The same is relevant for any other method of Promise class, like catch, finally`, etc.