Sub-project of Funfix, exposing primitive interfaces and data types that need to be universally available, belonging into a standard library.
Included are data types for expressing disjunctions:
Either | data type for expressing results with two possible outcome types (a disjoint union) |
Option | data type for expressing optional values |
Try | data type for representing the result of computations that may result in either success or failure |
Standard interfaces and tools for dealing with universal equality and hash code generation:
IEquals | an interface for defining universal equality and hash code |
is and equals | for using IEquals in tests, or otherwise falls back to JavaScript's equality (== or valueOf() ) |
hashCode | for calculating hash codes (for usage in sets and maps data structures) using IEquals , or otherwise falls back to calculating a hash from .valueOf() or from .toString() |
isValueObject | for testing if a given object implements IEquals |
Also exposes standard, reusable error types, that help with some common scenarios, working with error types being preferable to working with strings:
DummyError | for tagging errors used for testing purposes |
IllegalArgumentError | for signaling that a given argument is violating the contract of the called function or constructor |
IllegalInheritanceError | for signaling that inheriting from a certain class is illegal |
IllegalStateError | for signaling that an illegal code branch was executed and thus something is wrong with the code and needs investigation (e.g. a bug) |
NoSuchElementError | thrown when the user expects an element to be returned from a function call, but no such element exists |
NotImplementedError | thrown in case an implementation is missing |
TimeoutError | thrown in case the execution of a procedure takes longer than expected |
CompositeError | for gathering multiple errors in a single reference that can expose them as a list |
Misc utilities:
applyMixins | for working with mixins (i.e. classes used as interfaces, with methods that have default implementations), see Mixins for an explanation |
id | is the "identity" function |
You can depend on the whole funfix
library, by adding it to
package.json
:
npm install --save funfix
In this case imports are like:
import { Option } from "funfix"
Or for finer grained dependency management, the project can depend
only on funfix-core
:
npm install --save funfix-core
In this case imports are like:
import { Option } from "funfix-core"
Usage sample:
import { Try, Option, Either } from "funfix"
const opt1 = Option.of("hello")
const opt2 = Try.of(() => "world").toOption()
const greeting =
Option.map2(opt1, opt2, (a, b) => a + " " + b)
console.log(greeting.getOrElse("Ooops!"))
The library has been compiled using UMD (Universal Module Definition), so it should work with CommonJS and AMD.
But it also provides a module
definition in package.json
, thus
providing compatibility with
ECMAScript 2015 modules, for usage when used with a modern JS engine,
or when bundling with a tool chain that understands ES2015 modules,
like Rollup or Webpack.
Type enumerating the type-classes that Either
implements.
Type enumerating the type classes implemented by Option
.
Type alias for errors that can be thrown.
Since in JavaScript any object can be thrown, the standard
Error
class (capital E
) is not useful as a type in signatures,
the needed type being effectively any
, but we still need a type
alias for documentation purposes.
And since any
represents an untyped object that bypasses the
type system, Funfix is using Object
for TypeScript and mixed
for Flow to represent such throwables.
Type enumerating the type classes implemented by Try
.
The None
data constructor for Option represents non-existing
values for any type.
Using this reference directly is equivalent with Option.none.
The Some<A>
data constructor for Option represents existing
values of type A
.
Using this function is equivalent with Option.some.
Utility function for implementing mixins, based on the TypeScript Mixins documentation.
Sample:
class Disposable { ... }
class Activatable { ... }
class SmartObject implements Disposable, Activatable { ... }
applyMixins(SmartObject, [Disposable, Activatable]);
Using implements
instead of extends
for base classes
will make the type system treat them like interfaces instead of
classes. And by applyMixins
we can also supply global
implementations for the non-abstract members.
Given a function, converts it into a method where this
gets
passed around as the last argument.
Alias for is.
Universal hash-code function.
Depending on the given value, it calculates the hash-code like so:
number
, then it gets truncated
to an integer and returnedhashCode
is usedvalueOf()
function is provided, then the
hashCode
gets recursively invoked on its resultString
and a hash code is calculated using hashCodeOfStringis the value to use for calculating a hash code
an integer with the aforementioned properties
Calculates a hash code out of any string.
The identity function.
Tests for universal equality.
First attempting a reference check with ===
,
after which it tries to fallback on IEquals, if the
left-hand side is implementing it.
equals(10, 10) // true, because 10 === 10
class Box implements IEquals<Box> {
constructor(value: number) { this.value = value }
equals(other) { return this.value === other.value }
hashCode() { return this.value << 2 }
}
// false, because they are not the same reference
new Box(10) === new Box(10)
// true, because `Box#equals` gets called
equals(new Box(10), new Box(10))
Test if the given reference is a value object.
Value objects are objects that implement the IEquals interface.
is the reference to test
Type-class implementations, compatible with the static-land
and funland
specifications.
See funland-js.org.
Type-class implementations, compatible with the static-land
and funland
specification.
See funland-js.org.
Type-class implementations, compatible with the static-land
and funland
specifications.
See funland-js.org.
Returns a Setoid
type-class instance that depends
universal equality, as defined by is.
Generated using TypeDoc
Given a type
T
representing instances of a classC
, the typeConstructor<T>
is the type of the classC
.This type emulates Class from Flow .
Note that in TypeScript constructors can also be
protected
orprivate
and unfortunately specifying{ new(): T }
is thus insufficient. Which is why, for classes without a public constructor, we have to specify a_funErasure
(static) member as a property, to help the compiler infer typeT
.Example:
class NumBox { constructor(public num: number) {} } class GenBox<A> { constructor(public a: A) {} } function getDefault<F>(ref: Constructor<F>): Option<F> { if ((ref as any)._default) return Some(ref._default) return None } (NumBox as any)._default = new NumBox(10) (GenBox as any)._default = new GenBox("value") const r1: Option<NumBox> = getDefault(NumBox) const r2: Option<GenBox<any>> = getDefault(GenBox)
And for classes with a private constructor:
class PrivateBox<A> { private constructor(public a: A) {} static _funErasure: PrivateBox<any> // leaving undefined } const F = PrivateBox as any F._default = new F("hello") const r: Option<PrivateBox<any>> = getDefault(NumBox)