validated-method
v1.0.3
Published
Runtime type checking for JavaScript function parameters
Maintainers
Readme
ValidatedMethod
Provides runtime type checking for JavaScript function parameters similar to TypeScript, but with no compiling or dependencies.
Features
- Zero dependencies
- TypeScript-like parameter validation in pure JavaScript
- Named, single, and positional parameter support
- Coercion options for numbers and booleans
- Regular Expression validation for strings
- Custom type support
- Extra parameter warnings
- Optional return type validation
- Easy to integrate with intuitive syntax
- Supports async / Promsie chaining
- Full test suite included
Usage
import { ValidatedMethod } from './validated-method.js';
class UserService {
createUser = new ValidatedMethod({
username: 'string',
age: 'number',
active: 'boolean',
roles: 'array',
settings: 'object',
email: /^[^@]+@[^@]+\.[^@]+$/,
birthday: ['string', 'optional']
title: 'string'
}, async opts => {
// Parameters are validated, safe to use
return await db.users.create(opts);
});
}
const myService = new UserService();
myService.createUser({
username: 'besworks',
age: 40,
active: true,
roles: [ 'admin', 'wizard' ],
settings: { darkmode: 'auto' },
email: '[email protected]',
// birthday: is optional so undefined is ok
// Throw TypeError because title: is undefined
});
Type Validation
Basic Types
'string'- String values'boolean'- Truthy/Falsey values (coerced usingBoolean())'object'- Object literals'array'- Arrays of any length including 0'function'- Executable functions'null'- Empty values
Number Types
'int'- Integers with truncating coercion (usesparseInt())'roundint'- Integers with rounding coercion (usesMath.round())'strictint'- Integers without coercion'number'- Alias of'float''float'- Floating point numbers with coercion (usesparseFloat())'strictfloat'- Floating point numbers without coercion
Special Types
'any'- Any value includingnull, exceptundefined'undefined'- Alias of'optional''optional'- Value can beundefined'strictboolean'- Booleans only without coercion/^test$/ig- Regular Expression literal (without quotes, usestoString())ClassName- Class comparison (usinginstanceof)(a) => a === b- any declared or incline function can be used as a validator
Import Alias
The _$ helper is provided for convenience but can be renamed on import if it conflicts with other libraries:
import { _$ as VM } from './validated-method.js';
const getData = VM('string', performLookupByName);Custom Types
class Widget {
node = document.getElementById('widget')
?? document.createElement('custom-widget');
}
const configureWidget = _$({
widget: Widget,
className: 'string'
}, opts => {
opts.widget.node.classList.add(opts.className);
// safe to call classList because we know
// opts.widget.node is an HTMLElement
// and opts.className is a string
});
configureWidget(new Widget(), 'green');Extra Parameter Warnings
By default, ValidatedMethod warns about unexpected parameters:
const addRecord = _$({
name: 'string',
age: 'number'
}, insertData);
addRecord({
name: 'test',
age: 40,
extra: true // Warning: "Unexpected parameter: extra"
});Quiet Mode
You can globally supress warnings with the static quiet flag.
ValidatedMethod.quiet = true;
const getData = _$({
bleep: 'boolean',
bloop: 'array'
}, opts => {
return {
e: opts.bleep,
o: opts.bloop
}
});
const ref = {
bleep: true,
bloop: [],
derp: { ...bigObj },
zzz: 'more'
};
getData(ref); // no warnings, best for productionParameter Styles
Named Parameters
const method = _$(
{ name: 'string', age: 'number' },
opts => `${opts.name} is ${opts.age}`
);
method({ name: 'Test', age: 42 });Single Parameter
// Using type identifier
const $ = _$('string', query =>
document.querySelector(query)
);
$('.my-element');
// Using Custom class
const process = _$(
CustomType, instance => instance.process()
);Positional Parameters
const add = _$(
['number', 'number'], (a, b) => a + b
);
add(40, 2); // Returns 42
const delayed = _$(
['int', 'function'], (ms, callback) => setTimeout(callback, ms)
);
delayed(1000, () => console.log('Done!')); Zero Parameter Functions
For functions that take no parameters, you can use any of these equivalent forms:
// These all create a parameterless function that returns a number
const fn1 = _$(undefined, () => 42, 'number');
const fn2 = _$(null, () => 42, 'number');
const fn3 = _$('void', () => 42, 'number');
const fn4 = _$([], () => 42, 'number');
const result = fn1(); // Returns 42
fn1(42); // Throws: Expected 0 arguments, got 1Custom Validators
You can use functions as input type validators. They must be synchronous and return a truthy/falsey value.
const isEven = n => n % 2 === 0;
const getHalf = _$(isEven, num => num/2);
getHalf(42); // Accepted input
getHalf(43); // TypeError
// declared inline
const ref = 1;
const getExact = _$(
a => a === ref,
num => num
);Error Handling
Throws a TypeError for validation failures:
- Missing required parameters
- Type mismatches
- Coercion failures
- Invalid custom type instances
Return Type Validation
You can optionally specify an expected return type as the third parameter.
Supported Return Types
- All input type identifiers (
'string','number','boolean','null', etc) - Custom classes (validates instanceof)
- Regular expressions (tests string conversion)
- Array of types for multiple options
- Special types:
'void'orundefined- Must return undefined'any'- Any value except undefined'optional'- Included for completeness, this is the same as not specifying a return type. Return type is not checked.a => a === b- Use any declared or inline function to validate output
Return Type Examples
// Ensure function returns a string
const upperCase = _$(
'string', str => str.toUpperCase(), 'string'
);
// Validate class instances
// including custom and built in types
const getUser = _$(
'number', id => db.findUser(id), User
);
const getNodes = _$(
[ Node, 'string' ], (el, q) => el.querySelectorAll(q), NodeList
);
// Allow multiple return types
const getValue = _$(
'string', key => cache.get(key), ['string', 'null']
);
// Explicit void return, must return undefined
const logMessage = _$(
'string', msg => { console.log(msg); }, 'void'
);
// Any non-undefined return, null allowed
const process = _$(
'object', data => processData(data), 'any'
);
// Regular Expression test string output
const checkValue = _$(
'string', str => procesValue(str), /^testing$/i
);
// custom validator function
const offset = 10;
const getPositive = _$(
'number', num => num - offset, n => n > 0
);
getPositive(5); // returns -5, would fail validation
// check by reference
const complexTask = _$(
null, doSomething, checkResults
);