npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@mlhaufe/object-algebra

v0.1.1

Published

An implementation of Object Algebras

Downloads

3

Readme

Object Algebra

Build npm version Downloads

Implementation of Object Algebras to enable Feature-Oriented Programming (FOP).

Installation

The latest version:

npm install @mlhaufe/object-algebra

A specific version:

npm install @mlhaufe/[email protected]

For direct use in a browser (no build step):

<script type="importmap">
{
  "imports": {
    "@mlhaufe/object-algebra": "https://unpkg.com/@mlhaufe/object-algebra/index.mjs",
  }
}
</script>
<script type="module">
  import {Merge} from '@mlhaufe/object-algebra';

  console.log(typeof Merge); // 'function'
</script>

Usage

Declare the Algebra:

interface PointAlg<T> extends Algebra {
    Point2(x: number, y: number): T
    Point3(x: number, y: number, z: number): T
}

Define Data:

class PointData { }
class Point2 extends PointData {
    constructor(readonly x: number, readonly y: number) { super() }
}
class Point3 extends PointData {
    constructor(readonly x: number, readonly y: number, readonly z: number) { super() }
}

Define Factory for the data:

class PointDataFactory implements PointAlg<PointData> {
    Point2(x: number, y: number) {
        return new Point2(x, y)
    }
    Point3(x: number, y: number, z: number) {
        return new Point3(x, y, z)
    }
}

Define a couple traits:

interface IPrintable { print(): string }
class Printable implements PointAlg<IPrintable> {
    Point2(x: number, y: number): IPrintable {
        return {
            print() { return `(${x}, ${y})` }
        }
    }
    Point3(x: number, y: number, z: number): IPrintable {
        return {
            print() { return `(${x}, ${y}, ${z})` }
        }
    }
}

interface IAddable { add(other: PointData & IAddable): this }
class Addable implements PointAlg<IAddable & PointData> {
    Point2(x: number, y: number): IAddable & Point2 {
        const family = this
        return {
            add(other: Point2 & IAddable) { return family.Point2(x + other.x, y + other.y) }
        } as any
    }
    Point3(x: number, y: number, z: number): IAddable & Point3 {
        const family = this
        return {
            add(other: Point3 & IAddable) { return family.Point3(x + other.x, y + other.y, z + other.z) }
        } as any
    }
}

Compose the features into a single class:

import {Merge} from '@mlhaufe/object-algebra';

class PointFactory extends Merge(PointDataFactory, Printable, Addable) { }

// Alternatively:
// const PointFactory = Merge(PointDataFactory, Printable, Addable)

const { Point2, Point3 } = new PointFactory()

const p1 = Point2(1, 2)
const p2 = Point2(3, 4)

console.log(p1.print()) // (1, 2)
console.log(p2.print()) // (3, 4)

console.log(p1.add(p2).print()) // '(4, 6)'

More examples are available in the tests directory.

Future Work

TypeScript does not support Higher Kinded Types (#1213). This means that the Merge function will not track or merge the generics types of the composed classes. This is generally a problem for container types like List. You can see an example of in ListAlg.test.mts directory.

TypeScript also does not support associated types (#17588) so an emulation of HKTs are also not possible via that feature (As described by Bertrand Meyer). Index types are close, but seem to be forgotten by the compiler.

There is another approach to HKTs that does leverage indexed types to some limited success, but it adds an additional syntactic burden to the user which I find unacceptable.

References and Further Reading