
Security News
Feross on TBPN: How North Korea Hijacked Axios
Socket CEO Feross Aboukhadijeh breaks down how North Korea hijacked Axios and what it means for the future of software supply chain security.
@avanzu/std
Advanced tools
A rust inspired implementation of the Option and Result type with some additional functional flavor.
@avanzu/stdA rust inspired implementation of the Option and Result type with some additional functional flavor.
In genereal
Option type can be used for values that may be null or undefined.Result type can be used to express the outcome of a synchronous computation.OptionThe abstract Option type contains two concrete types that share an identical api.
Some<T> - the type that contains a concrete valueNone - the type that contains nothingAdapting the corresponding rust example function
const { Option } = require('@avanzu/std')
const divide = (numerator, denominator) =>
denominator == 0 ? Option.None() : Option.Some(numerator / denominator)
The return value of the function is an option.
let result = divide(2.0, 3.0)
Option.fold(onNone, onSome)Since javascript does not provide anything similar to rusts pattern matching, we need a different way to make sure that every branch is covered.
result.fold(
// the "None" branch must be handled
() => console.error('Cannot divide by 0'),
// before you can handle the "Some" branch
(x) => console.log('Result: ', x)
)
Releasing the value out of the Option type works also quite similar.
Option.unwrap()Some will return the wrapped value
Option.Some('FOO').unwrap()
// -> 'FOO'
None will "panic" and throw an exception
Option.None().unwrap()
// -> Error('Unable to unwrap Option<None>.')
Option.unwrapOr(defalut)Some will return the wrapped value
Option.Some('FOO').unwrap()
// -> 'FOO'
None will return the given default value
Option.None().unwrapOr('BAR')
// -> 'BAR'
Option.unwrapOrElse(callable)Some will return the wrapped value
Option.Some('FOO').unwrap()
// -> 'FOO'
None will return the value from the given callable
Option.None().unwrapOrElse(() => 'BAZ')
// -> 'BAZ'
ResultThe abstract Result type contains two concrete types that share an identical api.
Ok<T> - the type that contains the value of a successful computationErr<U> - the type that contains the error of a failed computationIt behaves very similar to the Option type with the only difference that the Err branch can also hold a value which is typically an Error.
Adapting the corresponding rust example function
const { Result } = require('@avanzu/std')
const Version = {
Version1: 'Version1',
Version2: 'Version2',
}
const parseVersion = ([num] = []) => {
switch (num) {
case undefined:
return Result.Err('invalid header length')
case 1:
return Result.Ok(Version.Version1)
case 2:
return Result.Ok(Version.Version2)
default:
return Result.Err('invalid version')
}
}
The return value of the function is a result.
let result = parseVersion([2])
Result.fold(onErr, onOk)Similar to the Option type, we can use fold to exhaust all branches.
result.fold(
// the "Err" branch must be handled
(e) => console.error('error parsing header', e),
// before you can handle the "Ok" branch
(x) => console.log('working with version: ', x)
)
Releasing the value out of the Result type works also quite similar.
Result.unwrap()Ok will return the wrapped value
Result.Ok('FOO').unwrap()
// -> 'FOO'
Err will "panic" and throw an exception
Result.Err('Does not compute.').unwrap()
// -> Error('Does not compute.')
Result.unwrapOr(defalut)Ok will return the wrapped value
Result.Ok('FOO').unwrap()
// -> 'FOO'
Err will return the given default value
Result.Err('Does not compute.').unwrapOr('BAR')
// -> 'BAR'
Result.unwrapOrElse(callable)Ok will return the wrapped value
Result.Ok('FOO').unwrap()
// -> 'FOO'
Err will return the value from the given callable
Result.Err('Does not compute.').unwrapOrElse(() => 'BAZ')
// -> 'BAZ'
Result.try(unsafeFunction)You can use Result.try to wrap an "unsafe" function that may throw an exception.
const parse = Result.try(JSON.parse)
With valid json, parse will return Ok<T> which you can unwrap.
parse('{"foo": "bar"}').unwrapOr({})
// { foo: 'bar' }
With invalid json, parse will return Err<U> which you can ignore and return a default value.
parse('{"foo": "bar"').unwrapOr({})
// -> {}
Both types provide a .promise() method that allows to transform seamlessly into a promise.
Option
Some will transform into a resolved promiseNone will transform into a rejected promiseResult
Ok will transform into a resolved promiseErr will transform into a rejected promiseTransforming from a promise into a result is not that simple due to the synchronous nature of Result. However, you can use await in parenthesis to make it work.
const p = Promise.resolve('OK')
(await Result.promised(p)).unwrap()
// 'OK'
important in order for this to work, you have to use parenthesis. Otherwise await will not know where the promise is supposed to end.
await Result.promised(p).unwrap()
// TypeError: Result.promised(...).unwrap is not a function
Both Option and Result provide some functional style methods for you to play with.
The following examples will only showcase with the
Resulttype but theOptiontype behaves identically.
T(a).map(a -> b) -> T(b)
You can safely use .map without worrying about null or error checks.
Result.Ok('foo')
.map((s) => s.toUpperCase())
.unwrapOr('')
// -> 'FOO'
Result.Err()
.map((s) => s.toUpperCase())
.unwrapOr('')
// -> ''
T.chain(a -> T(b)) -> T(b)
You can safely .chain Results or Options
Result.Ok('foo')
.chain((s) => Result.Ok(`${s}bar`))
.unwrapOr('')
// -> foobar
Result.Ok('foo')
.chain((s) => Result.Err('Does not compute.'))
.unwrapOr('')
// -> ''
T(a -> b).ap(T(a)) -> T(b)
You can apply a function inside a Result to a value in another Result.
const concat = (a) => (b) => `${a}-${b}`
Result.Ok(concat).ap(Result.Ok('foo')).ap(Result.Ok('bar')).unwrapOr('')
// foo-bar
Result.Ok(concat).ap(Result.Ok('foo')).ap(Result.Err()).unwrapOr('')
// ''
T(a|b).bimap((b -> c), (a -> d)) -> T(d|c)
You can assign a callback to each branch simultaneously. Similar to .fold the first callback is used for the error case and the second one for the success case.
const onErr = (err) => new Error('Changed')
const onOk = (value) => value.toUpperCase()
Result.Ok('foo').bimap(onErr, onOk).fold(console.error, console.log)
// -> 'FOO
Result.Err().bimap(onErr, onOk).fold(console.error, console.log)
// -> Error: Changed
T(a).concat(T(b)) -> T(ab)
You can .concat an arbitrary number of results or options together, provided that the value they are holding is also a semigroup (provides a .concat method) like strings or arrays.
Result.Ok('foo').concat(Result.Ok('bar')).unwrap()
// -> foobar
Result.Ok([1, 2])
.concat(Result.Ok([3, 4]))
.unwrap()
// -> [1,2,3,4]
If you do concat with a Result.Err the outcome will remain the first one that occurred.
Result.Ok('test')
.concat(Result.Err('Error1'))
.concat(Result.Err('Error2'))
.fold(console.error, console.log)
// -> Error: Error1
Option.Some('foo').concat(Option.Some('bar')).unwrap()
// -> foobar
Option.Some([1, 2])
.concat(Option.Some([3, 4]))
.unwrap()
// -> [1,2,3,4]
If you do concat with a Option.None the outcome will remain the previous one.
Option.Some('test')
.concat(Option.None())
.concat(Option.Some('!!!'))
.fold(console.error, console.log)
// -> test!!!
FAQs
A rust inspired implementation of the Option and Result type with some additional functional flavor.
We found that @avanzu/std demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Socket CEO Feross Aboukhadijeh breaks down how North Korea hijacked Axios and what it means for the future of software supply chain security.

Security News
OpenSSF has issued a high-severity advisory warning open source developers of an active Slack-based campaign using impersonation to deliver malware.

Research
/Security News
Malicious packages published to npm, PyPI, Go Modules, crates.io, and Packagist impersonate developer tooling to fetch staged malware, steal credentials and wallets, and enable remote access.