InferJS-Library allows you to easily add runtime type checking by utilizing JSDoc multi-line comments in both client and server side JavaScript. The library is part of a bigger project named InferJS.
InferJS is provided with an InferJS-Compiler. The compiler interprets your JSDoc comments from your source code and compiles them into an InferObject file, that you can import into any JavaScript file.
With this library, you can also enable extended type checking and narrow down your data types with @infer
expectation rules. Check out the examples below, to see how InferJS can save you time and money from costly bugs through development and release.
To install the latest version of InferJS-Library locally with npm
:
npm install inferjs-library --save
npm install -g inferjs-library
Optional: If you would like to download the repo source code with git
:
git clone https://github.com/Codevendor/inferjs-library.git
If you would like to use the InferJS-Library from the browser, please select a precompiled/minified
version and module type from the dist
folder. There are 3 types of modules supported (esmodule
,commonjs
,script
). The latest
folder contains the latest version of the library.
If you are missing the dist
folder or would like to compile the latest version, follow the steps below.
To build yourself, you will need to install Webpack version 5+ with the following commands. The commands need to be run from where the package.json
is located. Or you can install them globally with the -g
identifier.
// Local Install
npm install --save-dev webpack
npm install --save-dev webpack-cli
or
// Global Install
npm install -g --save-dev webpack
npm install -g --save-dev webpack-cli
The latest version of webpack 5+ automatically installs the terser-webpack-plugin with it. If it doesn't, you will need to install it as well, from where the package.json
is located. The Terser
plugin is used for minimizing/compressing
the library code for use in the browser.
npm install terser-webpack-plugin --save-dev
After the node modules under devDependencies
are installed, you can run the build process from where the package.json
is located.
npm run build
In order to use the InferJS-Library, you will need to compile an InferObject with the InferJS-Compiler.
For more information on installing the InferJS-Compiler and its usage click here.
Copy one of the minimized inferjs-{version}.min.js
from the dist
folder to your website. Copy the pre-compiled [InferObject]() file to your website, that was created with the InferJS-Compiler.
Add both to your webpage for type checking. You only need to recompile with the InferJS-Compiler, if you change your JSDoc multi-line comments, @param
, @type
, @inferid
or @infer
tags.
Below are examples for using InferJS-Library in your code.
<script type="module">
import { InferObject } from "./inferobject.js";
import { InferJS } from "./esmodule/inferjs-{version}.min.js";
const inferjs = new InferJS(InferObject);
</script>
<script src="https://github.com/Codevendor/inferjs-library/raw/main/inferobject.js"></script>
<script src="https://github.com/Codevendor/inferjs-library/raw/main/script/inferjs-{version}.min.js"></script>
<script>
const inferjs = new InferJS(InferObject);
</script>
import { InferObject } from "./inferobject.js";
import { InferJS } from "./esmodule/inferjs-{version}.min.js";
const inferjs = new InferJS(InferObject);
const InferObject = require("./inferobject.js");
const InferJS = require("./commonjs/inferjs-{version}.min.js");
const inferjs = new InferJS(InferObject);
There are many ways to utilize the InferJS-Library. The example above, imports in the pre-compiled [InferObject]() file that was created with the InferJS-Compiler. Intialize the InferJS-Library class with the [InferObject]() file you want to use.
// Intialize through constructor
const inferjs = new InferJS(InferObject);
// or intialize through property
const inferjs = new InferJS();
inferjs.inferObject = InferObject;
Once the InferJS-Library and [InferObject]() file are included at the top of your file you can then utilize the type checking features. Below is an example of how to create a JSDoc multi-line comment for type checking.
/**
* Test case scenario for JavaScript inferjs function.
* @category tests
* @function foo
* @param {string} msg - The message to send through console.log().
* @param {(number|string)} id - The id of the message.
* @param {boolean} [send=true] - Whether to send your message.
* @infer {string} msg {STRING-NOT-EMPTY} - Checks if string is not empty.
* @inferid foo
*/
function foo(msg, id, send) {
inferjs.check('foo', arguments);
}
// Example Normal Call
foo('test', 1234, true);
The JSDoc tag @param
below specifies a method's parameter type(s), name and description.
/**
* @param {string} msg - The message to send through console.log().
*/
/**
* @param {(null|string)} msg - The message to send through console.log().
*/
InferJS-Library reads the precompiled [InferObject]() file and uses it to process all type checking and inferred expectations.
Below is a list of standard
and extended types
that can be checked:
Standard JS Types | Description |
---|---|
[undefined]() | An undefined type: undefined |
[null]() | A null type: null |
[boolean]() | A boolean type: true or false |
[number]() | A number type: 1000 or 10.25 |
[bigint]() | A big integer type: 1010101112233343545545545446n |
[string]() | A string type: foo1 or foo2 |
[symbol]() | A symbol type: Symbol |
[function]() | A function type: function |
Extended InferJS Types | Description |
[any]() | Allows Any type: any or * |
[array]() | An array type: [] |
[infinity]() | An infinity number type: Infinity |
[nan]() | Not a number type: NaN |
[arguments]() | The arguments object: arguments . |
["className"]() | A class name: fooClass |
["functionName"]() | A function name: fooFunction |
["errorName"]() | An error type: Error or TypeError or errorName |
InferJS-Library also allows for extended type checking with the custom @infer
tag. Add one or multiple @infer
tags to any parameter type. This will allow for narrowing your types down through expectations.
Below is an simple example of @infer
:
/**
* @infer {string} msg {STRING-NOT-EMPTY} - Checks if string is not empty.
*/
The @infer
tag is so versatile you can attach it to multiple types in a group and specify multiple narrowing and values to check against, like so:
/**
* @infer {(number|string)} msg {INT32|STRING-NOT-EMPTY} - Checks if string is not empty and is an integer32.
* @infer {array} arrname {IN-ARRAY=a,b,c,d,e} - Checks if a,b,c,d is in array.
* @infer {object} objname {PROPS=id,name} - Checks if objname has properties id and name.
*/
There are many extended expectation types for narrowing your types down with your @infer
tags.
Below is a list of common rule expectation types:
Expectation | Description |
---|---|
[STRING-NOT-EMPTY]() | Checks if a string is not empty. |
[STRING-EMPTY]() | Checks if a string is empty. |
[IS-BOOL]() | Checks if a string is a boolean, true , false , yes , no , on , off , 0 , 1 . |
[BETWEEN]() | Checks if number is between two numbers. |
[BETWEEN-INCLUSIVE]() | Checks if number is between two numbers and including equal to self. |
[BETWEEN-BIGINT]() | Checks if string is between two big integers. |
[BETWEEN-BIGINT-INCLUSIVE]() | Checks if a string is between two big integers including equal to self. |
[GREATER-THAN]() | Checks if value is greater than. |
[GREATER-THAN-EQUAL]() | Checks if value is greater than equal. |
[LESS-THAN]() | Checks if value is less than. |
[LESS-THAN-EQUAL]() | Checks if value is less than equal. |
[REGEX]() | Checks if matches a regular expression. |
[ALPHA]() | Checks if alpha characters. |
[IS-NUMBER]() | Checks if a string is a number. |
[IS-BIGINT]() | Checks if a string is a bigint. |
[IS-NUMERIC]() | Checks if a string is numeric. |
[ALPHA-NUMERIC]() | Checks if a string is alpha numeric. |
[IN-ARRAY-CI]() | Checks if in array list case insensitive. |
[IN-ARRAY]() | Checks if in array list case sensitive. |
[NOT-IN-ARRAY-CI]() | Checks if not in array list case insensitive. |
[NOT-IN-ARRAY]() | Checks if not in array list case sensitive. |
[EXTENDS-ALL]() | Checks if object extends all types. |
[EXTENDS]() | Checks if object extends type. |
[PROPS]() | Checks if object contains properties. |
[ARRAY-NOT-EMPTY]() | Checks if array not empty. |
[ARRAY-EMPTY]() | Checks if array is empty. |
[ARRAY-TYPES]() | Checks if array items of are of expected types. |
[INT8]() | Checks for INT8: -128 to 127 |
[CHAR]() | ^ |
[UINT8]() | Checks for UINT8: 0 to 255 |
[UCHAR]() | ^ |
[UNSIGNED-CHAR]() | ^ |
[INT16]() | Checks for INT16: -32768 to 32767 |
[SHORT]() | ^ |
[SHORT-INT]() | ^ |
[SIGNED-SHORT]() | ^ |
[UINT16]() | Check for UINT16: 0 to 65535 |
[UNSIGNED-SHORT]() | ^ |
[UNSIGNED-SHORT-INT]() | ^ |
[USHORT]() | ^ |
[INT32]() | Check for INT32: -2147483648 to 2147483647 |
[SIGNED-INT]() | ^ |
[INT]() | ^ |
[UINT32]() | Check for UINT32: 0 to 4294967295 |
[UNSIGNED-INT]() | ^ |
[UINT]() | ^ |
[INT64]() | Check for INT64: -9223372036854775808 to 9223372036854775807 |
[SIGNED-LONG]() | ^ |
[SIGNED-LONG-LONG]() | ^ |
[LONG]() | ^ |
[LONG-LONG]() | ^ |
[UINT64]() | Check for UINT64: 0 to 18446744073709551615 |
[UNSIGNED-LONG]() | ^ |
[UNSIGNED-LONG-LONG]() | ^ |
[ULONG]() | ^ |
The tag @inferid
is a unique identifier for linking InferJS-Library behind the scenes. It is required for each method
, property
or field
, you would like to check.
This special tag, allows code to still work, while JavaScript is compressed/minified
or obfuscated
. All Infers are stored in a precompiled InferObject file. This makes it easy to write in your static data types and not have to worry about type checking them during JavaScript Runtime execution.
@inferid
can be anything you want as a name, but must be unique per item you want to check.
Below is an example of @inferid
:
/**
* @inferid foo
*/
To check all your types and expectations, you need to call the InferJS-Library method check()
. It needs to be added at the beginning of each method(s) starting closure or below each variable you would like to check.
Below is the overload signature for the method check() : |
Method Signature for InferJS-Library: check() |
---|---|
check ( inferId: [@inferid](), args: [arguments](), returnException: [boolean =]()false ) |
|
Description: Type checks all parameters in arguments list and either returns or throws exception. | |
check ( inferId: [@inferid](), arg: [field](), returnException: [boolean =]()false ) |
|
Description: Type checks single declared variables or fields. |
function foo(){
inferjs.check('Your - @inferid', arguments);
}
var a = 'foo';
inferjs.check('Your - @inferid', a);
In InferJS-Library you have the option to throw or return exception
from the check()
method. Thrown errors come with tons of information for debugging your types and expectations.
Exception Types | Description |
---|---|
InferUnhandledError | For all errors unhandled by the InferJS library. |
InferTypeError | For all type errors created from the JSDoc tag @param {type} |
InferExpectError | For all errors related to the custom JSDoc tag @infer and custom expectation rules. |
Below are examples of exception type responses from InferJS-Library.
InferTypeError: Incorrect third parameter type in:
File: /path/to/test1.js
Line: 14
@inferid: foo
@function: ( msg: <string>, id: <number>, objectTester: <object> )
@param: objectTester
Expected Type: object
Actual Type: null
InferExpectError: Incorrect first parameter, failed infer expectation type check in:
File: /path/to/test1.js
Line: 14
@inferid: foo
@function: foo( msg: <string|number|null>, id: <number|string>, send: <boolean> )
@param: msg
Expectation Type: STRING-NOT-EMPTY
Expectation Value: "1234"
Argument Value: ""
For more examples, please refer to the Documentation
Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are greatly appreciated.
If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag enhancement
.
Don't forget to give the project a [⭐ star](), Thanks again!
git checkout -b feature/AmazingFeature
)git commit -m 'Add some AmazingFeature'
)git push origin feature/AmazingFeature
)Distributed under the MIT License. See LICENSE.txt
for more information.