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

xtype

v0.0.7

Published

Simple object type checking

Downloads

25

Readme

xType

Simple object type checking

xType is just a simple way to quickly validate that an object is of a certain structure. It's goal is to be lightweight and fast.

Notes:

  • You currently can't inherit required properties using a check function.

Usage

xType exposes the following functions:

  • define
  • get
  • defineFn
  • getFn
  • guard
  • undefine
xtype.define(<name>, <type>, <options>)
  • name: name of the definition. Can only be used once.
  • type: the raw type of the object, such as 'object' or 'array'
  • options: an object or function that is used for validation
xtype.undefine(<name>)
  • name: name of the function to remove
xtype.defineFn(<name>, <types...>)
  • name: name of the function.
  • types: each argument of the function is given one argument
xtype.get(<name>)
  • name: name of the function
xtype.getFn(<name>)
  • name: name of the
xtype.guard(<name>, <fn>)
  • name: name of the function definition
  • fn: function to run if validation passes

Definitions

You use xType by creating 'definitions' that document what an object should consist of.

xtype.define('address', 'object', {
    keys: {
        street: 'string',
        city: 'string'
    }
});

var test = define('user', 'object', {
    keys: {
        id: 'number',
        name: 'string',
        address: 'address'
    }
});

test({
    id: 10,
    name: 'John',
    address: {
        number: 27,
        street: 'Road'
    }
});

Options

Keys

Keys allow you to specify what keys an object can have to be valid. If the type does not match, or if an object has a key that is not in 'keys', then it will return false.

var test = define('special_object', 'object', {
    keys: {
        id: 'number'
        name: 'string'
    }
});

test({ id: 10, name: 'word' }); // true
test({ id: 'word', name: 10 }); // false

test = define('special_array', 'array', {
    keys: {
        0: 'number',
        1: 'string'
    }
});

test([10, 'word']); // true
test(['word', 10]); // false

Required Keys

By default, all keys are optional. However, if you need to specify that an object is valid if it contains a key, you can set it as required.

Do this by prefixing the type with an asterisk.

var test = define('required', 'object', {
    keys: {
        id: '*number'
    }
});

test({id: 20}); // true
test({}); // false

Other

Other makes the test more flexible - meaning that it will ignore any properties on an object that

test = define('standard', 'object', {
    keys: {
        id: 'number'
    }
});

test({ id: 20, name: 'word' }); // false

test = define('flexible', 'object', {
    other: true,
    keys: {
        id: 'number'
    }
});

test({ id: 20, name: 'word' }); // true

All

Setting options.all means that all properties of the object must be that type.

This can only be used by itself, and cannot be used with 'keys', 'other' or 'inheritance'.

test = define('array_of_strings', 'array', {
    all: 'string'
});

test(['an', 'array', 'of', 'strings']); // true
test([1, 2, 3, 4, 5]); // false

Primitive Types

xType is very flexible about what types are. So you can easily use it with other type validation libraries.

If you supply a type and a function, they will be used to create a function that firsts check that an object is of that type, and if so will then check it against your function.

var email = define('email', 'string', function (str) {
    return !! str.match(/.+@.+\..+/);
});

email('[email protected]'); // true
email('johnsmitcom');    // false
email(30);               // false
email({{}});             // false


var validator = require('validator');
var uppercase = define('uppercase', 'string', validator.isUppercase);
uppercase('TRUE');
uppercase('FaLsE');
uppercase('false');

You can just have a completly raw function that will do all the checking. This is particulary useful for combining it with other libraries that already do type checking for you.

var array = define('array', function (obj) {
    Object.prototype.toString.call(obj) === '[object Array]';
});

Inheritance

xType allows you to split definitions in multiple sections, so you don't have to repeat yourself all the time.

xtype.define('model', 'object', {
    keys: {
        id: 'number',
        name: 'string'
    }
});

xtype.define('task', 'object', {
    inherit: 'model',
    keys: {
        completed: 'boolean',
        notes: 'string'
    }
});

xtype.define('taskArray', 'array', {
    all: 'task'
});

xtype.define('list', 'object', {
    inherit: 'model',
    keys: {
        tasks: 'taskArray'
    }
});

var task = xtype.get('task');
var list = xtype.get('list');

task({
    id: 20,
    name: 'Just a task',
    completed: true,
    notes: 'Finish xType'
}); // true

list({
    id: 10,
    tasks: [
        {
            id: 1,
            name: 'a task in a list',
            completed: false,
            notes: ''
        },
        {
            id: 2,
            name: 'another task',
            completed: false,
            notes: 'with some notes'
        }
    ]
}); // true

Fancy Inheritance

I haven't thought of a good name for this yet.

Basically you can choose which definition to inherit, based on the object.

To use it you set inherit as an possible definitions to inherit, as well as setting check to a function that accepts a single argument: object.

inherit can be an object or an array, but whatever the check function returns will be used to try and access the property from it.

xtype.define('a', 'object', {
    keys: {
        model: 'string'
    }
});

xtype.define('b', 'object', {
    keys: {
        model: 'number'
    }
});

xtype.define('c', 'object', {
    keys: {
        model: 'boolean'
    }
});


xtype.define('thing', 'object', {
    inherit: ['a', 'b', 'c'],
    check: function (obj) {
        switch (obj.type) {
            case 'a': return 0;
            case 'b': return 1;
            case 'c': return 2;
        }
    }
});

var thing = xtype.get('thing');

thing({
    type: 'a',
    model: 'string'
}); // true

thing({
    type: 'b',
    model: 30
}); // true

thing({
    type: 'c',
    model: true
}); // true

thing({
    type: 'd',
    model: true
}); // false - type d doesn't exist

Function Definitions

This is used to create definitions for function arguments.

defineFn

The first argument is the name of the function. The rest are the types of each argument. Every argument is required by default.

xtype.defineFn('my_fn', 'string', 'number');

Optional Properties

Prefix type with a ~ symbol.

It is best to use this only the last argument, as xType won't do anything special if you make the first argument optional.

var test = xtype.defineFn('my_fn', 'string', 'number', '~function');

test('word', 30); // true
test('word', 30, function () {}); // true

test = xtype.defineFn('my_fn_2', '~string', '~number');

test(); // true
test('word'); // true
test(undefined, 30); // true
test(30); // false

getFn

Use this to get a function definition by it's name.

Will throw an error if the definition doesn't exist.

var test = xtype.getFn('my_fn');

guard

Use this to 'guard' a function, that will only run if validation passes.

xtype.defineFn('my_fn', 'string', 'number');

var fn = function (string, number) {
    // can assume that string is actually a string
    // and that number is really a number
};

// Guard fn
var guard = xtype.guard('my_fn', fn);

// will call fn
guard('word', 30);

// will not call fn
guard();
guard('word');
guard(undefined, 30);