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.
Eq
for modelling equivalence relations.Ord
for modelling total orders.Semigroup
for modelling associative combination.
Neotype Prelude supplies a collection of data types for solving common problems in both syncrhonous and asynchronous contexts:
Annotation
andAsyncAnnotation
for logging and accumulating information in a non-error stateEither
andAsyncEither
for modelling failure or unions of valuesIor
andAsyncIor
for modelling failure with logging or inclusive unions of valuesMaybe
andAsyncMaybe
for modelling optional valuesPair
for modelling pairs of valuesValidation
andAsyncValidation
for 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/prelude
This 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: