Interfaces for JavaScript. Sort of.

Downloads in past


001.1.35 years ago6 years agoMinified + gzip package size for @darkobits/interface in KB


!travistravis-imgtravis-url !daviddavid-imgdavid-url !codacycodacy-imgcodacy-url !minifiedminified-imgunpkg-url !gzippedgzipped-imgunpkg-url !Code Stylexo-imgxo-url !NPM Versionnpm-imgnpm-url
Interfaces for JavaScript. Sort of.


$ npm install @darkobits/interface

The Interface class allows for the creation of contracts between an object and its consumers. Interfaces are constructed with a name and an optional list of argument types. This package also exports the Any value which can be used to indicate a desired minimum arity of an interface's implementation without enforcing argument types.
The value returned from the constructor can then be used in two ways:
  1. To implement the interface on classes/objects using implementedBy.
  2. As a key that can be used to invoke the interface on objects that implement it.

Interface performs a minimum arity check when implementations are registered and performs minimum arity and type-checking against invocations of implementations at runtime.
Note: Implementations are bound to their host objects, so in most cases arrow functions should not be used to define them.

Using with Classes

When provided a class or constructor function, Interface will install implementations on its prototype. In most cases, this is desired.
import Interface from '@darkobits/interface';

// Create a new interface, SetName, that should be used with one string argument.
const SetName = new Interface('SetName', [String]);

class Person {
  constructor () {
    this.name = '';

  getName () {
    return this.name;

// This implementation doesn't meet the minimum arity for the interface, so it will throw an error:
SetName.implementedBy(Person).as(function () {


// This will pass:
SetName.implementedBy(Person).as(function (str) {
  this.name = str;

// The interface can then be used thusly:
const frodo = new Person();

frodo[SetName]();                // Arity check will fail, this will throw an error.
frodo[SetName](null);            // Type check will fail, this will throw an error.
frodo[SetName]('Frodo Baggins'); // This will pass.

Using with Instances

In some cases, however, the interface may need to have access to a constructor function's closure. When passed an object, Interface will install the implementation onto the object directly.
import Interface from '@darkobits/interface';

const SetName = new Interface('SetName', [String]);

function Person () {
  let name = '';

  this.getName = () => {
    return name;

  SetName.implementedBy(this).as(function (str) {
    name = str;

const frodo = new Person();
frodo[SetName]('Frodo Baggins');

Using the Any Placeholder

import {
} from '@darkobits/interface';

// Create an interface to set a key/value pair. Keys should be strings, but values can be anything.
const SetData = new Interface('SetData', [String, Any]);

class Model {
  constructor () {
    this.data = {};

  getData (key) {
    return this.data[key];

SetData.implementedBy(Model).as(function (key, value) {
  this.data[key] = value;

const myModel = new Model();
myModel[SetData]('someData', [1, 2, 3]);
myModel[SetData]('otherData', 42);


Because almost everything in JavaScript is an object, it is not possible to have robust type-checking at runtime. For example, strings constructed with the String() constructor will pass an Object type check, as will functions and arrays.