closure-type

A pattern and helper library for augmenting the revealing module pattern with mixin support.

Usage no npm install needed!

<script type="module">
  import closureType from 'https://cdn.skypack.dev/closure-type';
</script>

README

closureType

closureType is a helper function for defining JavaScript object types using an enhanced version of the revealing module pattern that supports mixins.

Demo

// Create a "closure type" by invoking closureType with a callback.
// It will return to you a type factory function for creating instances.
var postType = closureType(
  // These args are passed to the main type and all function mixins.
  //
  // - `self` is an object to hold private instance state.
  // - `api` is the object returned from the type factory function, where
  //   you should attach all public methods and instance state.
  // - `initArgs` is a function that carries the arguments passed to the type
  //   factory function, taking a function for performing initialization logic.
  function(self, api, initArgs) {
    // Invoking init logic immediately.
    // You could also delay it with:
    //
    // var init = initArgs(function(title, body) {
    //   self.title = title;
    //   self.body = body;
    // });
    //
    // Then call `init()` later.
    initArgs(function(title, body) {
      self.title = title;
      self.body = body;
    })();

    // closureType.extend() is a handy helper function
    // for adding properties to the api object.
    closureType.extend(api, {
      getBody: function() {
        return self.body;
      },

      getTitle: function() {
        return self.title;
      },

      setBody: function(newBody) {
        if (!newBody) {
          return;
        }
        self.body = newBody;
        // We can use the mixed-in `emit()` method from
        // EventEmitter to notify subscribers of changes.
        api.emit('bodyChange', newBody);
      },

      setTitle: function(newTitle) {
        if (!newTitle) {
          return;
        }
        self.title = newTitle;
        api.emit('titleChange', newTitle);
      }
    });
  },
  // Mixins can be functions that take `self`, `api`, and `initArgs` or
  // objects (whose methods will be added to `api` with `this` bound to
  // `self`.
  [commentable, EventEmitter.prototype, likable]
);

// Mixins are just functions that take the closureType args.
function commentable(self, api, initArgs) {
  initArgs(function() {
    // Mixins can add instance state.
    self.comments = [];
  })();

  // Mixins can add public properties.
  closureType.extend(api, {
    addComment: function(comment) {
      self.comments.push(comment);
    },

    getComment: function(index) {
      return self.comments[index];
    },

    getComments: function() {
      return self.comments.slice();
    },

    numComments: function() {
      return self.comments.length;
    }
  });
}

function likable(self, api, initArgs) {
  initArgs(function() {
    self.numLikes = 0;
  })();

  closureType.extend(api, {
    addLike: function() {
      self.numLikes += 1;
    },

    numLikes: function() {
      return self.numLikes;
    }
  });
}

FAQ

Coming soon.