UNPKG

@neumatter/is

Version:

Module for type checking in javascript.

299 lines (263 loc) 5.89 kB
const toBuiltinType = input => { return Object.prototype.toString.call(input).slice(8, -1) } const toFirstUpperCase = input => { const first = input.slice(0, 1).toUpperCase() const rest = input.slice(1) return first + rest } const NOT_NUM_REGEX = /[a-z]+/i function toCustomType (input = 'Default', type) { const map = { Object: input?.constructor?.name !== 'Object' ? input?.constructor?.name : null, Function: input?.prototype?.constructor?.name || null, Default: null } return map[type] || null } function toDeepType (input = 'Default', type) { const map = { Number: input !== null && NOT_NUM_REGEX.test(input.toString()) ? input.toString().match(NOT_NUM_REGEX)[0] : null, Array: input && input[0] ? toBuiltinType(input[0]) : null, Default: null } return map[type] || null } /** @type {import('./types/index').NeuType} */ export class NeuType { #proto #creator #builtin #deeptype #custom constructor (input, options) { const basejs = toBuiltinType(input) options = options || {} if (options.shallow) { this.#proto = null this.#builtin = basejs === 'AsyncFunction' ? 'Function' : basejs this.#deeptype = null this.#custom = null } else { this.#proto = input?.constructor?.prototype || null if (basejs === 'AsyncFunction') { this.#builtin = 'Function' this.#deeptype = 'AsyncFunction' } else { this.#builtin = basejs this.#deeptype = toDeepType(input, basejs) || null } this.#custom = toCustomType(input, basejs) || null if (/Function\[[a-zA-Z]+]/.test(this.tag)) { this.#creator = input } if (/Object\[[a-zA-Z]+]/.test(this.tag) && this.#deeptype) { this.#creator = input.constructor || null } } } [Symbol.toPrimitive] (hint) { return this.tag } get [Symbol.toStringTag] () { return this.tag } toString () { return this.tag } get tag () { return ( (this.#custom && `${this.#custom}[${this.#builtin.toLowerCase()}]`) || (this.#builtin === 'Array' && `Array<${this.#deeptype || 'any'}>`) || (!this.#deeptype && this.#builtin) || (`${this.#builtin}[${this.#deeptype || 'any'}]`) ) } get class () { return ( (this.#creator && this.#deeptype) || null ) } new (input) { if (this.#creator) return new this.#creator(input) } is (type) { const instance = (obj) => this.instance(obj) const istype = (el) => { el = toFirstUpperCase(el) return ( (this.#builtin === el) || (this.#builtin !== 'Array' && this.#deeptype === el) || (this.#custom === el) || false ) } return (typeof type === 'string' ? istype : instance)(type) } instance (instance) { return this.#proto instanceof instance } equals (input) { return this.tag === new NeuType(input).tag } } export function typeOf (input) { return new NeuType(input) } /** @type {import('./types/index').IS} */ export default class IS { static toType (input) { return toBuiltinType(input) } static instance (input, instance) { return new NeuType(input).instance(instance) } /** * * @param {*} input * @returns {boolean} */ static array (input) { return IS.toType(input) === 'Array' } /** * * @param {*} input * @returns {boolean} */ static object (input) { return IS.toType(input) === 'Object' } /** * * @param {*} input * @returns {boolean} */ static emptyObject (input) { return IS.toType(input) === 'Object' && !Object.keys(input).length } /** * * @param {*} input * @returns {boolean} */ static string (input) { return IS.toType(input) === 'String' } /** * * @param {*} input * @returns {boolean} */ static emptyString (input) { return input === '' } /** * * @param {*} input * @returns {boolean} */ static boolean (input) { return new NeuType(input, { shallow: true }).is('Boolean') } /** * * @param {*} input * @returns {boolean} */ static number (input) { return new NeuType(input, { shallow: true }).is('Number') } /** * * @param {*} input * @returns {boolean} */ static null (input) { return new NeuType(input, { shallow: true }).is('Null') } /** * * @param {*} input * @returns {boolean} */ static NaN (input) { return new NeuType(input).tag === 'Number[NaN]' } /** * * @param {*} input * @returns {boolean} */ static infinite (input) { return new NeuType(input).is('Infinite') } /** * * @param {*} input * @returns {boolean} */ static date (input) { return new NeuType(input, true).is('Date') } /** * * @param {*} input * @returns {boolean} */ static undefined (input) { return new NeuType(input, { shallow: true }).is('Undefined') } /** * * @param {*} input * @returns {boolean} */ static function (input) { return new NeuType(input, { shallow: true }).is('Function') } /** * * @param {*} input * @returns {boolean} */ static symbol (input) { return new NeuType(input, { shallow: true }).is('Symbol') } /** * * @param {*} input * @returns {boolean} */ static regex (input) { return new NeuType(input, { shallow: true }).is('RegExp') } /** * * @param {*} input * @returns {boolean} */ static emptyArray (input) { return new NeuType(input, { shallow: true }).is('Array') && !input.length } /** * * @param {*} input * @returns {boolean} */ static falseType (input) { return ( IS.null(input) || IS.undefined(input) || IS.emptyString(input) || IS.emptyArray(input) ) } }