Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/zxch3n/throwable
A type-safe way to work with error (Haskell's Either | Rust's Result)
https://github.com/zxch3n/throwable
Last synced: 21 days ago
JSON representation
A type-safe way to work with error (Haskell's Either | Rust's Result)
- Host: GitHub
- URL: https://github.com/zxch3n/throwable
- Owner: zxch3n
- Created: 2021-08-21T09:25:22.000Z (about 3 years ago)
- Default Branch: master
- Last Pushed: 2022-01-17T08:21:29.000Z (almost 3 years ago)
- Last Synced: 2024-10-04T16:22:05.128Z (about 1 month ago)
- Language: TypeScript
- Homepage:
- Size: 91.8 KB
- Stars: 12
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
Awesome Lists containing this project
README
# Throwable
> A type-safe way to handle Error in TypeScript
[![codecov](https://codecov.io/gh/zxch3n/throwable/branch/master/graph/badge.svg?token=YPRRWO1EDZ)](https://codecov.io/gh/zxch3n/throwable)
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 withHaskell'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));
}```
## Usage
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
```ts
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 `this.value` is not error, then return `func(this.value)`
* otherwise return `this.error`
*/
pipe(func: (value: TReturn) => T): Throwable;
/**
* if this.value is valid, return this.value, otherwise return sub
*/
or(sub: T): TReturn | T;
/**
* if this.value is valid return it, otherwise throw the error
*/
unwrap(): TReturn;
}function Ok(v: TReturn): Throwable;
function Err(v: TError): Throwable;
```### `Use Case`
```ts
type MThrowable = Throwable;function readJsonFile(path: string): Promise{
...
}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());
}
```