letype
Version:
Type checker for any data structures
233 lines (190 loc) • 6.79 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(global = global || self, factory(global.Letype = {}));
}(this, (function (exports) { 'use strict';
var CustomType = function CustomType () {};
var Any = /*@__PURE__*/(function (CustomType) {
function Any () {
CustomType.apply(this, arguments);
}
if ( CustomType ) Any.__proto__ = CustomType;
Any.prototype = Object.create( CustomType && CustomType.prototype );
Any.prototype.constructor = Any;
Any.prototype.parse = function parse () {
return true;
};
return Any;
}(CustomType));
/**
* @param {any} value
* @param {Function|RegExp|Array|Record<any, any>} type
* @param {string[]} path
* @param {boolean} silent
* @returns {boolean}
*/
function typeCheck(value, type, path, silent) {
if ( path === void 0 ) path = [];
if ( silent === void 0 ) silent = true;
if (typeof type === 'function' && type.prototype instanceof CustomType) {
// @ts-ignore
// eslint-disable-next-line new-cap
var ref = new type();
var parse = ref.parse;
if (typeof parse === 'function') { return parse(value); }
}
var retype = ((typeof type === 'function') ? type() : type);
/** @type {string} */
var typed = typeof retype;
var constructorsMatch = value !== undefined && value !== null && value.constructor === type;
if (type === Date) {
return constructorsMatch;
}
if (type && type.constructor === RegExp && retype instanceof RegExp) {
/** @type {boolean} */
var typeChecked = retype.test(value);
if (!typeChecked && !silent) {
console.error(("Type error: Expected " + (path.length > 0 ? ("`" + (path.join('.')) + "`") : 'value') + " as `" + value + "` to pass regexp `" + retype + "`"));
}
return typeChecked;
}
if (type === RegExp) {
return constructorsMatch;
}
if (constructorsMatch) {
return true;
}
if (typed === 'object' && typeof value === 'object') {
var valid = true;
// Uncalled Array function
if (type && type instanceof Function && type.name === 'Array' && type.constructor instanceof Function) {
return (value && value.constructor) === (type && type.constructor);
}
if (type instanceof Array && type.length === 1) {
if (!(value && value.length > -1)) {
return false;
}
// eslint-disable-next-line no-restricted-syntax
for (var item in value) {
if ({}.hasOwnProperty.call(value, item)) {
var typeChecked$1 = typeCheck(value[item], type[0], path.concat(item), silent);
if (valid) {
valid = typeChecked$1;
}
}
}
} else {
var newValue = Object.assign({}, type, value);
// eslint-disable-next-line no-restricted-syntax
for (var item$1 in newValue) {
if ({}.hasOwnProperty.call(newValue, item$1)) {
var typeChecked$2 = typeCheck(newValue[item$1], type[item$1], path.concat(item$1), silent);
if (valid) {
valid = typeChecked$2;
}
}
}
}
return valid;
}
// eslint-disable-next-line valid-typeof
var checked = typeof value === typed;
if (!checked) {
if (value === undefined) {
if (!silent) {
console.error(("Type error: " + (path.length > 0 ? ("`" + (path.join('.')) + "`") : 'Value') + " is undefined! Required value of type `" + typed + "`"));
}
} else
if (retype === undefined) {
if (!silent) {
console.error(("Type error: " + (path.length > 0 ? ("`" + (path.join('.')) + "`") : 'Value') + " is defined as `" + value + "`! But it should not be defined at all!"));
}
} else
if (!silent) {
console.error(("Type error: `" + value + "` is not of type `" + typed + "`" + (path.length > 0 ? (" in `" + (path.join('.')) + "`") : '')));
}
}
return checked;
}
/**
* @param {any} value
* @param {any[]} typeList
* @returns {boolean}
*/
function assert(value) {
var typeList = [], len = arguments.length - 1;
while ( len-- > 0 ) typeList[ len ] = arguments[ len + 1 ];
if (typeList && typeList.length === 1) {
if (!typeCheck(value, typeList[0], [], true)) {
throw new TypeError('Type checker found some type mismatches!');
}
} else
if (typeList && typeList.length > 1) {
var valid = false;
typeList.forEach(function (type) { return !valid && (valid = typeCheck(value, type, [], true)); });
if (!valid) {
throw new TypeError(("`" + value + "` is not any of types: " + (typeList.map(function (t) { return ("`" + (t.name) + "`"); }).join(', '))));
}
}
return true;
}
/**
* @param {any[]} types
* @returns {typeof OrType}
*/
function Or() {
var types = [], len = arguments.length;
while ( len-- ) types[ len ] = arguments[ len ];
var OrType = /*@__PURE__*/(function (CustomType) {
function OrType () {
CustomType.apply(this, arguments);
}
if ( CustomType ) OrType.__proto__ = CustomType;
OrType.prototype = Object.create( CustomType && CustomType.prototype );
OrType.prototype.constructor = OrType;
OrType.prototype.parse = function parse (value) {
return assert.apply(void 0, [ value ].concat( types ));
};
return OrType;
}(CustomType));
return OrType;
}
var Undefined = /*@__PURE__*/(function (CustomType) {
function Undefined () {
CustomType.apply(this, arguments);
}
if ( CustomType ) Undefined.__proto__ = CustomType;
Undefined.prototype = Object.create( CustomType && CustomType.prototype );
Undefined.prototype.constructor = Undefined;
Undefined.prototype.parse = function parse (value) {
return typeof value === 'undefined';
};
return Undefined;
}(CustomType));
var types = {
Any: Any,
Or: Or,
Custom: CustomType,
Undefined: Undefined,
};
/**
* @param {any} value
* @param {any[]} typeList
* @returns {boolean}
*/
function check(value) {
var typeList = [], len = arguments.length - 1;
while ( len-- > 0 ) typeList[ len ] = arguments[ len + 1 ];
try {
assert.apply(void 0, [ value ].concat( typeList ));
} catch (e) {
return false;
}
return true;
}
exports.assert = assert;
exports.check = check;
exports.types = types;
Object.defineProperty(exports, '__esModule', { value: true });
})));
//# sourceMappingURL=letype.js.map