JavaScript

The class feature of modern JavaScript offers a good way to group a fact constructor with a set of specification functions. The type is added as a prototype field.

class Tag {
    constructor(
        name
    ) {
        this.type = Tag.Type;
        this.name = name;
    }
}
Tag.Type = "Blog.Tag";

A fact can then be created with the new operator.

const tagReact = await j.fact(new Tag("React"));

Specification Functions

Using static methods of a class, you can group specification functions with the type to which they belong.

class Post {
    constructor (
        created,
        author
    ) {
        this.type = Post.Type;
        this.created = created;
        this.author = author;
    }

    static byAuthor(author) {
        return j.match({
            type: Post.Type,
            author
        });
    }
}
Post.Type = "Blog.Post";

Specification functions belong either with their parameter type or their result type. Successor specifications as shown above are best kept with the result type. This is because the predecessor (the author in this example) has no dependency upon the successor. There is no need to create that dependency by putting the specification function there. This also makes the queries easier to read.

const posts = await j.query(author, j.for(Post.byAuthor));

Predecessor Specifications

Some specification functions return a predecessor. This is most common in authorization rules.

class Post {
    constructor (
        created,
        author
    ) {
        this.type = Post.Type;
        this.created = created;
        this.author = author;
    }

    static author(post) {
        post.has("author");
        return j.match(post.author);
    }
}
Post.Type = "Blog.Post";

function authorizeBlog(a) {
    return a
        .type(Post.Type, j.for(Post.author))
        ;
}

By convention, the specification function has the same name as the predecessor. It will not conflict, because the specification function is static while the predecessor is an instance field.

Continue With

TypeScript