stdlazy
TypeScript icon, indicating that this package has built-in type declarations

1.0.4 • Public • Published

stdlazy

A TypeScript-first lazy primitive that brings all the best bits of promises to lazy evaluation.

  • 🦥 On-demand evaluation.
  • ⌚ Support for async initializers.
  • ⚙️ Multiple strongly-typed operators.
  • 🫥 Use the Lazy type directly or return it as a () => T for a cleaner API.

Install

Using yarn:

yarn add stdlazy

Or npm:

npm install --save stdlazy

Pullables

A Pullable is an object that provides a pull() that returns a value, which is also called its pull value. The pull method is idempotent – calling it more than once should return the same result and cause no additional side-effects.

Like a Thenable, a Pullable will never produce another Pullable. If this would happen, it will instead pull it by invoking the pull() method, and return whatever it returns. This means Pullables can be chained transparently, just like promises.

The type operator that gives the pull value of a type T (which might be a Pullable) is Pulled<T>. It works just like Awaited<T>

The Lazy object offered by stdlazy is a Pullable, but has a lot more functionality besides.

Construction

Use the lazy factory function to wrap another function. This function can be sync or async, and can even return another Pullable that will be flattened.

import { lazy } from "stdlazy"

const lz = lazy(() => 1) satisfies Lazy<number>

const lzLz = (lazy(() => lazy1).pull() + 1) satisfies number

const lzAsync = lazy(async () => 1) satisfies LazyAsync<number>

stdlazy uses the same type – Lazy<T> – to represent both sync and async lazy values. An async lazy value is just a Lazy<Promise<T>>, which is also referred under the alias LazyAsync<T>.

This is also known as its FINAL FORM. The factory function will flatten all standard compositions of the Lazy and Promise types into this FINAL FORM.

lazy(async () => {
    return lazy(async () => {
        return 5
    })
}) satisfies LazyAsync<number>

Operators

The Lazy type implements several operators for working with lazy values.

Map

Project the (awaited) pull value of a Lazy instance.

// The operator projects the Pulled value of a Lazy:
const lz = lazy(() => 1).map(x => x + 1)
console.log(lz.pull()) // 2

// If the lazy is async, it projects that Pulled and Awaited value instead, cutting through both container types.
const asyncLz = lazy(async () => 1).map(x + 1)
console.log(await lz.pull()) // 2

The map operator creates a new Lazy value, backed by an existing one. When it’s pulled, it will pull the existing instance and project its (awaited) pull value using a function.

This callback won’t be executed until the pull() method on the outermost Lazy instance is called and, if it returns a Promise, that Promise resolves.

If the projection returns another Pullable, its pull() method will be called automatically. This allows chaining Pullables just like chaining promises.

If either the current Lazy instance or the projection is async, the result will be a LazyAsync.

Do

Perform an action with the (awaited) pull value of a Lazy instance.

const lz = lazy(() => 1).do(console.log)
console.log(lz.pull()) // 1

The do operator produces a new Lazy instance, backed by an existing one. When it’s pulled, it will pull the existing instance and invoke the given callback before producing the value unchanged.

If either the current Lazy instance or the callback is async, the result will be LazyAsync.

Zip

Combines a Lazy with one or more other Pullables into a single Lazy value.

const lz1 = lazy(() => 1)
const lz2 = lazy(() => 2)
const zipped = lz1.zip(lz2)
console.log(zipped.pull()) // [1, 2]

The zip operator zips together an existing Lazy value with other Pullables, producing a single Lazy producing an array of their values, in the order in which they were specified.

If any of the Lazy instances involved are async, the result will be a LazyAsync.

Assemble

Combine multiple pullables into a single pullable returning an object

const lz1 = lazy(() => 1)
const lz2 = lazy(() => "hello")
const assembled = lz1.assemble({
    other: lz2
})
console.log(assembled.pull()) // {this: 1, other: "hello"}

The assemble operator combines an existing Lazy instance with other Pullables, given as an object with Pullable values. It returns a single Lazy instance with the same keys and the values replaced by the pull values of each of them Pullables

The Lazy instance on which the operation was performed is considered to have the key this

If any of hte Lazy instances involved are async, the result will be LazyAsync.

Package Sidebar

Install

npm i stdlazy

Weekly Downloads

1

Version

1.0.4

License

MIT

Unpacked Size

64.7 kB

Total Files

27

Last publish

Collaborators

  • gregros