UNPKG

variant-type

Version:

A Variant is a data structure that can be used to represent any other data type.

75 lines (72 loc) 2.38 kB
var checkArgTypes = require('check-arg-types'); var hasProp = Object.prototype.hasOwnProperty; var DEFAULT_HANDLER = "_"; function getTestFunc(f) { var str = f.toString(); if (str.includes("native code")) { return function (v) { return checkArgTypes.toType(v) === checkArgTypes.toType(f()); }; } else { return f; } } function VariantFactory(types) { var Variant = {}; var typeNames = Object.keys(types).concat([DEFAULT_HANDLER]); if (typeNames.includes("case")) { throw new Error("`case` is a reserved key!"); } var checkArgs = function checkArgs(args, caseKey) { if (caseKey === DEFAULT_HANDLER) { return; } var len = types[caseKey].length; if (args.length !== len) { throw new Error("Arguments did not match for " + caseKey + ": Expected " + len + ", Received " + args.length); } var validators = types[caseKey]; for (var x = 0; x < len; x++) { var validator = validators[x]; var value = args[x]; if (!getTestFunc(validator)(value)) { throw new TypeError("\"" + value + "\" is not a valid " + validator.name + "!"); } } }; typeNames.forEach(function (type) { Variant[type] = function TypeClosure() { var args = [].slice.call(arguments); checkArgs(args, type); args.type = type; return args; }; }); function caseFunc(cases) { var Cases = {}; var caseKeys = Object.keys(cases); caseKeys.forEach(function (caseKey) { if (!typeNames.includes(caseKey)) { throw new Error("Invalid case key given for Variant: `" + caseKey + "` not in [" + typeNames.join(", ") + "]"); } Cases[caseKey] = function TypeCase() { var args = Array.prototype.slice.call(arguments); checkArgs(args, caseKey); return cases[caseKey].apply(null, args); }; }); return function handleCaseValue(getType) { var args = typeof getType === "function" ? getType() : getType; var handler = hasProp.call(Cases, args.type) ? Cases[args.type] : Cases[DEFAULT_HANDLER]; if (!handler) { throw new Error("No handler found for case: " + args.type); } return handler.apply(null, args); }; } Variant["case"] = caseFunc; Variant.on = caseFunc; return Object.freeze(Variant); } module.exports = VariantFactory; //# sourceMappingURL=variant-type.js.map