🦾 A type-safe way to express error
npm install @typ3/throwable
> A type-safe way to handle Error in TypeScript

Why
By default, we use try, catch, throw to handle error in JS/TS. But it's not type-safe -- we cannot tell what error a function may throw. It makes throw risky -- any unhandled error will make the program crash, which probably is not something we want.
All we need is a way to semantically tell us there might be a error that should be handled.
- T | undefined lacks of detail info
- T | Error is not convenient to work with
Haskell's Either type might be a solution to this scenario. This project rename it to Throwable for better readability.
We can use Throwable to mark a return type of a function to declare it will return TError if error occurred, otherwise TReturn;
``ts
function div(a: number, b: number): Throwable
if (b === 0) {
return Err('divZero');
}
if (Number.isNaN(b)) {
return Err('divNaN');
}
return Ok(a / b);
}
function aDivBDivB(a: number, b: number): Throwable
return div(a, b).ifOk(c => div(c, b));
}
`
Install
``
yarn add @typ3/throwable
Basic usage
`ts
import {Ok, Err, Throwable} from '@typ3/throwable'
// in deno
import {Ok, Err, Throwable} from 'https://deno.land/x/throwable@v0'
function parse(input: string): Throwable
const ans = []
if (!input.startsWith('{')) {
// Rather than throw new Error()
return Err('invalid');
}
...
return Ok(ans);
}
`
Throwable interface
`tsthis.value
interface Throwable
/**
* return the concrete error if it is an error
*/
get error(): TError | undefined
/**
* return the value if it is not an error
*/
get value(): TReturn | undefined
get isOk(): boolean;
get isError(): boolean;
/**
* if is not error, then return func(this.value)this.error
* otherwise return
*/
pipe
/**
* if this.value is valid, return this.value, otherwise return sub
*/
or
/**
* if this.value is valid return it, otherwise throw the error
*/
unwrap(): TReturn;
}
function Ok
function Err
`
`ts
type MThrowable = Throwable
function readJsonFile
...
}
async function readName(path: string): Promise
return (await readJsonFile(path)).pipe(x => x.name);
}
function getValidNames(paths: string[]): Promise
return Promise.all(paths.map(readName)).filter(x => x.isOk());
}
``