@colevoss/result v0.0.2
Result TS
This package provides Result<T, E>
and Option<T>
classes heavily inspired by Rust's standard library equivalents.
Why
After writing some Rust code, I realized how nice the Result
and Option
types
are to use. I wanted to have the same powerful types in my TypeScript code.
I have no idea if these types will actually be usable, but creating this package
allowed me to learn Rust's types even better as well as improving my TypeScript skills.
Rust has some very helpful language primitives like match
and ?
that empower
these types even further, and I've tried to capture some of the value of those
language features in this library as well.
Docs
Result<T, E>
// Example Results
const okResult = new Ok('ok value');
const errResult = new Err('error value');
and
and<U>(andValue: Result<U, E>): Result<U, E>
Returns andValue
if the Result is Ok
, otherwise returns Err
value.
Examples
const x = new Ok('x');
const y = new Ok('y')
const xAndY = x.and(y);
assert.equal(xAndY.unwrap(), 'y');
const x = new Err('early error');
const y = new Ok('y');
const xAndY = x.and(y);
assert.equal(x.unwrapErr(), 'early error');
const x = new Ok('x');
const y = new Err('late error');
const xAndY = x.and(y);
assert.equal(xAndY.unwrapErr(), 'late error');
const x = new Err('early error');
const y = new Err('late error');
const xAndY = x.and(y);
assert.equal(xAndY.unwrapErr(), 'early error');
andThen
andThen<U>(cb: (v: T) => Result<U, E>): Result<U, E>
Calls cb
if Result is Ok
, otherwise returns Err<E>
.
Examples
const x = new Ok('x');
const y = x.andThen((xVal) => {
return new Ok(xVal + ' new')
});
assert.equal(y.unwrap(), 'x new');
const x = new Ok('x');
const y = x.andThen((xVal) => {
return new Err('error')
});
assert.equal(y.unwrapErr(), 'error');
const x = new Err('early error'):
const y = x.andThen(() => {
return new Ok('ok')
});
assert.equal(y.unwrapErr(), 'early error');
err
err(): Option.Option<E>
Converts from Result<T, E>
to Option<E>
Examples
const x = new Err('error');
const y = x.err(); // Some('error')
assert.ok(y.isSome());
assert.equal(y.unwrap(), 'error')
const x = new Ok('ok');
const y = x.err(); // None
assert.ok(y.isNone());
expect
expect(reason: string): T
Returns the contained value T
if value is Ok
.
Throws
Throws error if Result is Err
with provided reason as message and cause
as this
Examples
// Ok
const x = new Ok('ok value');
const xVal = x.expect('Should be ok value');
assert.equal(xVal, 'ok value')
// Err
const x = new Err('error value');
const xVal = x.expect('should be ok value');
// Throws:
// Error: should be ok value
// [cause]: Err [ResultError]: error value
// type: 'ResultError',
// error: 'error value'
// }
// }
expectErr
expectErr(reason: string): E
Returns the contained Err
value.
Throws
Throws contained value T
if Result is Ok<T>
// Err
const x = new Err('err value');
const xVal = x.expectErr('should be err value');
assert.equal(xVal, 'err value')
// Ok
const x = new Ok('ok value')
const xVal = x.expectErr('should be err value')
// Throws
// Error: should be error value
// [cause]: 'ok value'
// }
inspect
inspect(cb: (v: T) => void): this
Calls the provided function with contained value if Result is Ok
.
Ignores callback if Result is Err
Examples
// Ok
const x = new Ok('ok value');
x.inspect((xVal) => {
// logs "val: ok value"
console.log("val: ", xVal)
}); // returns x
// Err
const x = new Err('err value');
x.inspect(() => {
// is not called
});
inspectErr
inspectErr(cb: (e: E) => void): this
Calls the provided function with contained error if Result is Err
Ignores callback if Result is Ok
Examples
// Err
const x = new Err('error value');
x.inspectErr((xVal) => {
assert.equal(xVal, 'error value');
}); // returns x
// Ok
const x = new Ok('ok value');
x.inspectErr(() => {
// is not called
})
isErr
isErr(): this is Err<E>; // boolean
Returns false
if Result is Err
Example
const x = new Ok();
assert.ok(!x.isErr());
const y = new Err('error');
assert.ok(y.isErr())
isErrAnd
isErrAnd(cb: (v: E) => boolean): boolean
Returns true
when Result is Err
and the contained error matches predicate
Examples
// Ok
const x = new Err(1);
const y = x.isErrAnd((xVal) => {
return x === 1;
});
assert.ok(y);
// Err
const x = new Ok(1);
const y = x.isErrAnd((xVal) => {
// is not called
});
assert.ok(!y);
isOk
isOk(): this is Ok<T>; // boolean
Returns true
if Result is Ok
Example
const x = new Ok();
assert.ok(x.isOk())
const y = new Err('error');
assert.ok(!y.isOk())
isOkAnd
isOkAnd(cb: (v: T) => boolean): boolean
Returns true
when Result is Ok and the contained value matches predicate
Examples
// Ok
const x = new Ok(1);
const y = x.isOkAnd((xVal) => {
return x === 1;
});
assert.ok(y);
// Err
const x = new Err(1);
const y = x.isOkAnd((xVal) => {
// is not called
});
assert.ok(!y);
map
map<U>(cb: (value: T) => U): Result<U, E>
Maps Result<T, E>
to Result<U, E>
by applying a function to a contained Ok
value and ignores if Err
.
Examples
const x = new Ok('ok');
const y = x.map((xVal) => {
return xVal.length;
});
assert.equal(y.unwrap(), 2);
mapOr
mapOr<U>(cb: (v: T) => U, orValue: U): U
Returns the provided default if Result is Err
otherwise applies a function
to the contained Ok
value (if Ok
).
Examples
// Ok
const x = new Ok('ok');
const y = x.mapOr((xVal) => {
return xVal.length;
}, 10);
assert.equal(y, 2);
// Err
const x = new Err('err');
const y = x.mapOr((xVal) => {
return xVal.length;
}, 10);
assert.equal(y, 10);
mapOrElse
mapOrElse<U>(okCb: (v: T) => U, errCb: (e: Err<E>) => U): U
Maps a Result<T, E>
to U
by applying fallback function errCb
to a contained
Err
value, or function okCb
to a contained Ok
value.
Examples
// Ok
const cb = (val) => val.length;
const x = new Ok('ok');
const y = x.mapOrElse(cb, cb);
assert.equal(y, 2);
// Err
const x = new Err('err');
const y = x.mapOrElse(cb, cb);
assert.equal(y, 3);
ok
ok(): Option<T>
Converts from Result<T, E>
to Option<T>
. Ok<T>
is converted to Some<T>
and
Err<E>
is converted to None
.
Examples
// Ok
const x = new Ok('ok val');
const y = x.ok();
assert.ok(y.isSome());
assert.equal(y.unwrap(), 'ok val'):
// Err
const x = new Err('err val');
const y = x.ok();
assert.ok(y.isNone());
or
or<F>(orValue: Result<T, F>): Result<T, F>
Returns orValue
if Result is Err
otherwise returns Ok
Examples
// Ok or Err
const x = new Ok('ok');
const y = new Err('late error');
const xOrY = x.or(y);
assert.ok(xOrY.isOk());
assert.equal(xOrY.unwrap(), 'ok');
// Err or Ok
const x = new Err('early error');
const y = new Ok('ok');
const xOrY = x.or(y);
assert.ok(xOrY.isOk());
assert.equal(xOrY.unwrap(), 'ok');
// Err or Err
const x = new Err('early error');
const y = new Err('late error');
const xOrY = x.or(y);
assert.ok(xOrY.isErr());
assert.equal(xOrY.unwrapErr(), 'late error');
// Ok or Ok
const x = new Ok('ok');
const y = new Ok('late ok');
const xOrY = x.or(y);
assert.ok(xOrY.isOk());
assert.equal(xOrY.unwrap(), 'ok');
orElse
orElse<F>(cb: (e: E) => Result<T, F>): Result<T, F>;
Calls cb
if Result is Err
, otherwise returns Ok
Examples
const o = new Ok('o')
const e = new Err('e')
const createOk = () => new Ok('ok');
const createErr = () => new Err('err');
assert.equal(o.orElse(createOk).unwrap(), 'o')
assert.equal(o.orElse(createErr).unwrap(), 'o')
assert.equal(e.orElse(createOk).unwrap(), 'ok')
assert.equal(e.orElse(createErr).unwrapErr(), 'err')
unwrap
unwrap(): T
If value is Ok<T>
returns T
.
Throw
Throws error if value is Err
Examples
// Ok
const x = new Ok('ok val');
assert.equal(x.unwrap(), 'ok val');
// Err
const x = new Err('err val');
x.unwrap() // Throws
// Err [ResultError]: err val
// type: 'ResultError',
// error: 'err val'
// }
unwrapErr
unwrapErr(): E
If Result is Err
returns E.
Throws
Throws error if value is Ok
Examples
// Err
const x = new Err('err val');
assert.equal(x.unwrapErr(), 'err val');
// Ok
const x = new Ok('ok val')
x.unwrapErr(); // Throws
// Err [ResultError]: ok val
// type: 'ResultError',
// error: 'ok val'
// }
unwrapOr
unwrapOr(orValue: T): T
Returns the contained Ok
value or provided default
Examples
// Ok
const x = new Ok(1);
assert.equal(x.unwrapOr(0), 1);
// Err
const x = new Err('error');
assert.equal(x.unwrapOr(0), 0);
unwrapOrElse
unwrapOrElse(cb: (e: E) => T): T
Returns the contained Ok
value or computes it from callback
const cb = (err) => 'or else';
// Ok
const x = new Ok('ok');
assert.equal(x.unwrapOrElse(cb), 'ok')
// Err
const x = new Err('ok');
assert.equal(x.unwrapOrElse(cb), 'or else')
Option
// Example Option
const someOption = new Some('some value');
const noneOption = new None();
and
and<U>(andValue: Option<U>): Option<U>;
Returns andValue
if the Result is Ok
, otherwise returns Err
value.
Examples
// Some and None
const x = new Some(1);
const y = new None();
assert.ok(x.and(y).isNone());
// None and Some
const x = new None();
const y = new Some(1);
assert.ok(x.and(y).isNone())
// Some and Some
const x = new Some(1);
const y = new Some(2);
assert.equal(x.and(y).unwrap(), 2);
// None and None
const x = new None();
const y = new None();
assert.ok(x.and(y).isNone());
andThen
andThen<U>(cb: (v: T) => Option<U>): Option<U>
Returns None
if Option is None
, otherwise calls cb
with contained value and
returns result.
Example
// Some and Some
const x = new Some('some');
const y = x.andThen((xVal) => new Some(xVal + 'thing'));
assert.equal(y.unwrap(), 'something');
// Some and None
const x = new Some('some');
const y = x.andThen((xVal) => new None());
assert.ok(y.isNone());
// None and Some
const x = new None();
const y = x.andThen(() => new Some('some'));
assert.ok(y.isNone());
// None and None
const x = new None();
const y = x.andThen(() => new None());
assert.ok(y.isNone());
expect
expect(reason: string): T
Returns the contained valued T
if value is Some
Throw
Throws error is Option is None
with provided reason as message.
Examples
// Ok
const x = new Some('some')
assert.equal(x.expect('should be some'), 'ok');
// Err
const x = new None()
x.expect('should be some'): // Throws
// Err [ResultError]: should be some
// type: 'ResultError',
// error: 'should be some'
// }
filter
filter(predicate: (v: T) => boolean): Option<T>
Returns None
if the option is None
, otherwise calls predicate
with the contained
value and returns:
Some<T>
ifpredicate
returnstrue
.None
ifpredicate
returnsfalse
.
Examples
const isEven = (n) => n % 2 === 0
const odd = new Some(1):
assert.ok(odd.filter(isEven).isNone());
const even = new Some(2);
assert.ok(even.filter(isEven).isSome());
assert.equal(even.filter(isEven).unwrap(), 2);
const none = new None();
assert.ok(none.filter(isEven).isNone());
inspect
inspect(cb: (v: T) => void): this
Calls the provided cb
with contained value (if Some
)
Examples
// Some
const x = new Some('some val')
x.inspect((someVal) => {
// logs "val: some val"
console.log('val:', someVal);
});
// None
const x = new None()
x.inspect((someVal) => {
// not called
});
isNone
isNone(): this is None;
Returns true
if Option is None
Examples
// Some
const x = new Some('some');
assert.ok(!x.isNone());
// None
const x = new None();
assert.ok(x.isNone());
isSome
isSome(): this is Some<T>
Returns true
if Option is Some
Examples
// Some
const x = new Some('some');
assert.ok(x.isSome());
// None
const x = new None();
assert.ok(!x.isSome());
isSomeAnd
isSomeAnd(cb: (v: T) => boolean): boolean
If type is Some<T>
returns value returned by the given callback.
If type is None
, returns false.
Examples
// Some
const isOne = (n) => n === 1;
const x = new Some(1);
const y = new Some(2);
assert.ok(x.isSomeAnd(isOne));
assert.ok(!y.isSomeAnd(isOne));
// None
const x = new None();
assert.ok(!x.isSomeAnd(isOne));
map
map<U>(cb: (value: T) => U): Option<U>
Maps Option<T>
to Option<U>
by applying a function to a contained Option
value
and ignores None
.
Examples
const len = (s) => s.length;
// Some
const x = new Some('some');
assert.equal(x.map(len).unwrap(), 4);
// None
const y = new None();
assert.ok(y.map(len).isNone());
mapOr
mapOr<U>(cb: (value: T) => U, orValue: U): U;
Returns the provided default if Option is None
otherwise applies a function to
the contained Option
value (if Some
).
*Examples
const len = (s) => s.length;
// Some
const x = new Some('some');
assert.equal(x.mapOr(len, 0), 4);
// None
const x = new None();
assert.equal(x.mapOr(len, 0), 0);
mapOrElse
mapOrElse<U>(someCb: (v: T) => U, noneCb: () => U): U
Maps an Option<T>
to U
by calling a fallback function noneCb
, or someCb
to a contained Some
value
Examples
const len = (s) => s.length;
const noneLen = () => 10000;
// Some
const x = new Some('some');
assert.equal(x.mapOrElse(len, noneLen), 4);
const x = new None();
assert.equal(x.mapOrElse(len, noneLen), 10000);
okOr
okOr<E>(errValue: E): Result<T, E>
Transforms the Option<T>
into Result<T, E>
, mapping Some<T>
to Ok<T>
and
None
to Err<E>
.
Examples
// Some
const x = new Some('some');
const res = x.okOr('bad');
assert.ok(res.isOk());
assert.equal(res.unwrap(), 'some');
// None
const x = new None();
const res = x.okOr('bad')
assert.ok(res.isErr());
assert.equal(res.unwrapErr(), 'bad');
okOrElse
okOrElse<E>(errCb: () => E): Result<T, E>
Transforms the Option<T>
into Result<T, E>
, mapping Some<T>
to Ok<T>
and
None
to Err<errCb()>
.
Examples
const orElseZero = () => 0;
// Some
const x = new Some(1);
const res = x.okOrElse(orElseZero);
assert.ok(x.isOk());
assert.equal(x.unwrap(), 1);
// None
const x = new None();
const res = x.okOrElse(orElseZero);
assert.ok(x.isErr());
assert.equal(x.unwrapErr(), 0);
or
or(orValue: Option<T>): Option<T>
Returns the option if it contains a value, otherwise returns orValue
.
Examples
// Some or Some
const x = new Some(1);
const y = new Some(2);
const or = x.or(y);
assert.equal(x.unwrap(), 1);
// Some or None
const x = new Some(1);
const y = new None();
const or = x.or(y);
assert.equal(x.unwrap(), 1);
// None or Some
const x = new None();
const y = new Some(2);
const or = x.or(y);
assert.equal(x.unwrap(), 2);
// None or None
const x = new None();
const y = new None();
const or = x.or(y);
assert.ok(x.isNone());
orElse
orElse(cb: () => Option<T>): Option<T>
Returns the option if it contains a value, otherwise calls cb
and returns the result.
Examples
const orNone = () => new None();
const orSome = () => new Some(10);
// Some or Some
const x = new Some(1);
const orElse = x.orElse(orSome);
assert.equal(x.unwrap(), 1);
// Some or None
const x = new Some(1);
const orElse = x.orElse(orNone);
assert.equal(x.unwrap(), 1);
// None or Some
const x = new None(1);
const orElse = x.orElse(orSome);
assert.equal(x.unwrap(), 10);
// None or Some
const x = new None(1);
const orElse = x.orElse(orNone);
assert.ok(x.isNone());
unwrap
unwrap(): T
If value is Some<T>
returns T
.
Throws
Throws error if Option is None
Examples
// Some
const x = new Some('some value');
assert.equal(x.unwrap(), 'some value');
// None
const x = new None();
x.unwrap(); // Throws
// Err [ResultError]: Option value is None
// type: 'ResultError',
// error: 'Option value is None'
// }
unwrapOr
unwrapOr(orValue: T): T;
If value is Some<T>
returns T
.
If value is None
returns given orValue
Examples
// Some
const x = new Some('some value');
assert.equal(x.unwrapOr('none value'), 'some value');
// None
const x = new None();
assert.equal(x.unwrapOr('none value'), 'none value');
unwrapOrElse
unwrapOrElse(cb: () => T): T
Returns the contained Some
value or computes it from the given callback.
Examples
const orElse = () => 'or else';
// Some
const x = new Some('some');
assert.equal(x.unwrapOrElse(orElse), 'some')
// None
const x = new None();
assert.equal(x.unwrapOrElse(orElse), 'or else')
xor
xor(xorValue: Option<T>): Option<T>
Returns Some
if exactly one of this
or xorValue
is Some
, otherwise returns
None
// Some xor Some
const x = new Some(1);
const y = new Some(2);
const xor = x.xor(y);
assert.ok(x.isNone());
// Some xor None
const x = new Some(1);
const y = new None();
const xor = x.xor(y);
assert.ok(x.isSome());
assert.equal(x.unwrap(), 1);
// Some xor None
const x = new None();
const y = new Some(2);
const xor = x.xor(y);
assert.ok(x.isSome());
assert.equal(x.unwrap(), 2);
// None xor None
const x = new None();
const y = new Some(2);
const xor = x.xor(y);
assert.ok(x.isNone());