Functional programming essentials for TypeScript
Neotype Prelude provides several contracts that each describe a structure and a set of laws for which data types can define their own implementation.
Eqfor modelling equivalence relations.Ordfor modelling total orders.Semigroupfor modelling associative combination.
Neotype Prelude supplies a collection of data types for solving common problems in both syncrhonous and asynchronous contexts:
AnnotationandAsyncAnnotationfor logging and accumulating information in a non-error stateEitherandAsyncEitherfor modelling failure or unions of valuesIorandAsyncIorfor modelling failure with logging or inclusive unions of valuesMaybeandAsyncMaybefor modelling optional valuesPairfor modelling pairs of valuesValidationandAsyncValidationfor modelling accumulating failures, like when validating data
Generator comprehensions are reusable, composable generator functions that compose functional data types in an imperative style. They support all native syntax (conditional statements, loops and iteration, try/catch/finally, etc.).
import { Maybe } from "@neotype/prelude/maybe.js";
declare function parseInteger(input: string): Maybe<number>;
declare function checkEven(input: number): Maybe<number>;
function* goParseEvenInteger(input: string): Maybe.Go<number> {
const int = yield* parseInteger(input);
const evenInt = yield* checkEven(int);
return evenInt;
}
const maybeEvenInt = Maybe.go(goParseEvenInteger(42));
console.log(maybeEvenInt);Generator comprehension syntax is available for the Annotation, Either,
Ior, and Maybe data types.
Async generator comprehensions add the power of promises and async/await
syntax to their synchronous counterparts for working seamlessly with async data
types.
import { AsyncMaybe } from "@neotype/prelude/async.js";
declare function fetchAuthorIdByEmail(email: string): AsyncMaybe<number>;
declare function fetchPostsByAuthorId(id: number): AsyncMaybe<string[]>;
async function* goFetchPostsByAuthorEmail(
email: string,
): AsyncMaybe.Go<string[]> {
const authorId = yield* await fetchAuthorIdByEmail(email);
const posts = yield* await fetchPostsByAuthorId(authorId);
return posts;
}
AsyncMaybe.go(goFetchPostsByAuthorEmail("test@example.com"))
.then(console.log)
.catch(console.error);Async generator comprehension syntax is available for the AsyncAnnotation,
AsyncEither,AsyncIor, and AsyncMaybe data types.
Neotype Prelude strives to:
- promote a fluent functional programming style via a chainable method-based API
- utilize idiomatic JavaScript and TypeScript programming patterns
- provide seamless interoperability with asynchronous workflows (native
promises,
async/await, async iteration, etc.) by avoiding wrapper types and relying instead on existing language features.
Neotype Prelude is available on NPM.
npm install @neotype/preludeThis library provides a suite of ES6 modules. A .js suffix is required in
all import statements. See each module's documentation for recommended import
practices and available exports.
This library takes inspiration from many existing functional programming languages and libraries, including: