JoMak / safeJs

Adding type safety and some other features to javascript

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

SafeJs

NPM

Description

This JavaScript library provides some extra utility features such as type checking, polling tasks (comming soon) and possibly other features.

Documentation

Run grunt docs inside the project root directory to generate API docs for all properties of the sjs object.

Currently, only runtime parameter type checking, i.e. sjs.func is under implementation. Basic type checking is completed, however additional features (such as type checking for variadic parameters) still needs to be completed.

sjs.func

Summary

The sjs.func method will wrap the function passed to it that will check the type of its parameters before running the passed in method.

Syntax

func(params, method[, context, methodName])  {function}
Parameters
  • params: An object or array containing the type definitions of each parameter that will be type checked (in the order they appear in the method).
    • Object form: { <Parameter Name>: <Type Definition>, ... }
    • Array form: [ <Type Definition>, ... ]
  • method: The method whose parameter types should be checked with the passed in type definitions
  • context (Optional): The value to use as this when executing the method
  • methodName (Optional): The method name to display in any invalid type error messages that are thrown
Returns

A wrapped function that will check the types of its parameters before executing method.

Throws

A TypeDefinitionError object containing the names of the method and parameter (if available) and the type definition that the parameter value mismatches.

Type Definitions

Type definitions can be represented in many ways:

  1. A string: This is a string describing one of the following primitive JavaScript types: element, array, object, function, string, number, boolean, date, regexp. e.g.

    sjs.func({ 
      param1: 'string' 
    }, function(param1...
  2. A Prototype object: This will make sjs.func check that the parameter value is an instance of the passed in object. For example, the following type definition lets the method run if param1 is an object that is an instance of the Error object/class:

    sjs.func({
      param1: Error.prototype
    }, function(param1...
  3. A function: This will make sjs.func pass in the parameter value to the method to determine if it meets the proper type requirements. The method must explicity return true if the passed in value is the correct type and false otherwise - truthy and falsey values won't work. For example, the following type definition lets the method run if param1 is an object that contains properties named test and hi:

    sjs.func({
      param1: function(val) {
        return (!_.isUndefined(val.test) && ~_.isUndefined(val.hi));
      }
    }, function(param1...
  4. An array of styles 1, 2 and/or 3: This will ensure that the parameter value matches at least one of the given types. e.g.

    sjs.func({ 
      param1: ['string', Array.prototype],
    }, function(param1...
  5. Styles 1, 2, 3 or 4 under a types property inside an object: This will allow additional properties to be added to the parameter defintion. e.g.

    sjs.func({ 
      param1: {
        types: ['string', Array.prototype],
        allowNull: true
        ...
      }
    }, function(param1...
  6. An instance of an sjs.TypeDefinition object: This is a special class that all of the above type defintions will ultimately get converted to. It contains the types the parameter is allowed to be, along with it's name and any [additional properties](# additional-properties) described below. Any of the above representations of a type definition can be passed into the constructor of sjs.TypeDefinition. e.g.

    sjs.func({ 
      param1: new sjs.TypeDefinition({
        types: ['string', Array.prototype],
        ...
      })
    }, function(param1...
Container Types

To specify the types of objects inside an array (i.e. to check for an array for strings), place the type definition inside an array. e.g.

var myMethod = sjs.func({
  param1: [['string', 'number']]
}, function(param1) {
  console.log("I ran!");
});

myMethod(['a', 6, 7]);
> "I ran!"

The above type definition for param1 checks to see if param1 is an array that contains either strings or numbers. To define a type definition in which param1 is allowed to be either an array of strings or an array of numbers, two different container type definitions need to be passed in. e.g.

var myMethod = sjs.func({
  param1: [['string'], ['number']]
}, function(param1) {
  console.log("I ran!");
});

myMethod(['a']);
> "I ran!"

myMethod([6, 'a']);
> "TypeDefinitionError: Error: Object: param1 has invalid types. Expected types: [[string], [number]]. Found type: object"
Additional Properties

The types definitions following style 4 and 5 can have the following additional properties:

  1. (Boolean) allowUndefined[=false]: Whether the parameter is allowed to be undefined. Alternatively, just undefined can be passed in as a type. e.g.

    sjs.func({ 
      param1: {
        types: 'string',
        allowUndefined: false,
      }
    }, function(param1...
  2. (Boolean) allowNull[=false]: Whether the parameter is allowed to be null. Alternatively, just null can be passed in as a type. e.g.

    sjs.func({ 
      param1: {
        types: 'string',
        allowNull: false,
      }
    }, function(param1...
  3. (Boolean) allowEmpty[=true]: Whether the parameter is allowed to be empty. e.g.

    sjs.func({ 
      param1: new sjs.TypeDefinition({
        types: 'string',
        allowEmpty: false,
      })
    }, function(param1...
  4. (String) objectName: Override the name of the parameter that will get displayed in TypeDefinitionError error messages. e.g.

    sjs.func({ 
      param1: {
        types: 'string',
        objectName: 'anotherName',
      }
    }, function(param1...
Additional Examples
var myFunction = sjs.func({
	param1: {
		types: [["string"], "number", MyCustomObject.prototype],
		allowEmpty: false,
		allowNull: true
	},
	param2: 'string',
  // Note: passing in `null` and `undefined` is the same as setting `allowNull` and `allowUndefined` respectively
	param3: ['function', null, undefined]

}, function myFunction(param1, param2, param3) {
   console.log ('I ran!', param1, param2, param3);
}, this);

//will throw
myFunction([6], 4, 'a string');
> "TypeDefinitionError: [myFunction] Error: Object: param1 has invalid types. Expected types: [[string], number, [object Object]]. Found type: object."

//will run
myFunction(['12'], 'a string', function(){});
> I ran! ["12"] a string function (){}

There is also an array version to represent type definitions (to make creating functions from sjs.func seem less intrusive).

var myFunction = sjs.func([[['string']], 'number', 'function'], function myFunction(param1, param2, param3) {
    console.log('I ran!', param1, param2, param3);
}, this, 'CustomName');

//will throw
myFunction({}, 4, 'a string');
> "TypeDefinitionError: [CustomName] Error: Object: 0 has invalid types. Expected types: [[string]]. Found type: object."

The tradeoff with this method is that the error messages will only provide the index of the parameter that did not follow its type definition rather than the name of the parameter.

Running

As a browser library

The latest versions of the library are be under the dist folder. safeJs requires underscorejs as a dependency, however there is an sjs-standalone version which includes underscore.

Building

  1. Run npm install inside the root directory
  2. Run grunt inside the root directory to build safeJs for browsers.

Roadmap

Position of Parameters
  • The func method should also allow types definitions to not be placed in the order the parameters are occuring in the function (i.e. by specifying a pos property to specify a position)
Variadic Type Definitions
  • Ideally, the func method should allow parameter definitions for variadic parameters (e.g. defining a type definition for all parameters after the third parameter).
Overlapping Type Definitions
  • This feature would kind of be like the opposite of the Variadic Type Definitions feature: Allow for multiple Type definitions to define the type of a single parameter.
  • Not sure if I want this to be a feature or not. Depends on how much overhead it ends up introducing...
Better build script
  • Ideally, I'd like to provide as much customization as possible to create custom 'sjs' libraries that only have the modules each user would like and wish to use.

Compatability

Browser Compatability was checked using JavaScript Compatibility Checker.

Desktop

IE Chrome Firefox Opera Safari
10+ 11+ 4+ 12+ 5.1+

Mobile

Opera Mini iOS Safari
5.0+ 7.0+

About

Adding type safety and some other features to javascript

License:Apache License 2.0


Languages

Language:JavaScript 100.0%