typechecker
Version:
Utilities to get and check variable types (isString, isPlainObject, isRegExp, etc)
186 lines (185 loc) • 6.28 kB
JavaScript
;
/* eslint quote-props:0 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.getType = exports.typeMap = exports.isEmptyKeys = exports.isEmptyWeakMap = exports.isEmptyMap = exports.isEmptyPlainObject = exports.isEmptyArray = exports.isWeakMap = exports.isMap = exports.isNullish = exports.isUndefined = exports.isNull = exports.isBoolean = exports.isString = exports.isNumber = exports.isArray = exports.isRegExp = exports.isFunction = exports.isAsyncFunction = exports.isSyncFunction = exports.isArguments = exports.isDate = exports.isError = exports.isClass = exports.isConventionalClass = exports.isNativeClass = exports.isPlainObject = exports.isObject = exports.getObjectType = void 0;
// Prepare
var isClassRegex = /^class\s|^function\s+[A-Z]/;
var isConventionalClassRegex = /^function\s+[A-Z]/;
var isNativeClassRegex = /^class\s/;
// -----------------------------------
// Values
/** Get the object type string */
function getObjectType(value) {
return Object.prototype.toString.call(value);
}
exports.getObjectType = getObjectType;
function isObject(value) {
// null and undefined are objects, hence the extra check
return value != null && typeof value === 'object';
}
exports.isObject = isObject;
function isPlainObject(value) {
/* eslint no-proto:0 */
// null and undefined are objects, hence the extra check
return value != null && value.__proto__ === Object.prototype;
}
exports.isPlainObject = isPlainObject;
function isNativeClass(value) {
// NOTE TO DEVELOPER: If any of this changes, isClass must also be updated
return (typeof value === 'function' && isNativeClassRegex.test(value.toString()));
}
exports.isNativeClass = isNativeClass;
function isConventionalClass(value) {
return (typeof value === 'function' &&
isConventionalClassRegex.test(value.toString()));
}
exports.isConventionalClass = isConventionalClass;
function isClass(value) {
return typeof value === 'function' && isClassRegex.test(value.toString());
}
exports.isClass = isClass;
function isError(value) {
return value instanceof Error;
}
exports.isError = isError;
function isDate(value) {
return getObjectType(value) === '[object Date]';
}
exports.isDate = isDate;
function isArguments(value) {
return getObjectType(value) === '[object Arguments]';
}
exports.isArguments = isArguments;
function isSyncFunction(value) {
return getObjectType(value) === '[object Function]';
}
exports.isSyncFunction = isSyncFunction;
function isAsyncFunction(value) {
return getObjectType(value) === '[object AsyncFunction]';
}
exports.isAsyncFunction = isAsyncFunction;
function isFunction(value) {
return isSyncFunction(value) || isAsyncFunction(value);
}
exports.isFunction = isFunction;
function isRegExp(value) {
return getObjectType(value) === '[object RegExp]';
}
exports.isRegExp = isRegExp;
function isArray(value) {
return ((typeof Array.isArray === 'function' && Array.isArray(value)) ||
getObjectType(value) === '[object Array]');
}
exports.isArray = isArray;
function isNumber(value) {
return typeof value === 'number' || getObjectType(value) === '[object Number]';
}
exports.isNumber = isNumber;
function isString(value) {
return typeof value === 'string' || getObjectType(value) === '[object String]';
}
exports.isString = isString;
function isBoolean(value) {
return (value === true ||
value === false ||
getObjectType(value) === '[object Boolean]');
}
exports.isBoolean = isBoolean;
function isNull(value) {
return value === null;
}
exports.isNull = isNull;
function isUndefined(value) {
return typeof value === 'undefined';
}
exports.isUndefined = isUndefined;
function isNullish(value) {
return value == null;
}
exports.isNullish = isNullish;
function isMap(value) {
return getObjectType(value) === '[object Map]';
}
exports.isMap = isMap;
function isWeakMap(value) {
return getObjectType(value) === '[object WeakMap]';
}
exports.isWeakMap = isWeakMap;
function isEmptyArray(value) {
if (!isArray(value))
throw new Error('value was not an array');
return value.length === 0;
}
exports.isEmptyArray = isEmptyArray;
function isEmptyPlainObject(value) {
if (!isPlainObject(value))
throw new Error('value was not a plain object');
// We could use Object.keys, but this is more efficient
for (var key in value) {
if (value.hasOwnProperty(key)) {
return false;
}
}
return true;
}
exports.isEmptyPlainObject = isEmptyPlainObject;
function isEmptyMap(value) {
if (!isMap(value))
throw new Error('value was not a map');
return value.size === 0;
}
exports.isEmptyMap = isEmptyMap;
function isEmptyWeakMap(value) {
if (!isWeakMap(value))
throw new Error('value was not a weak map');
return Object.keys(value).length === 0;
}
exports.isEmptyWeakMap = isEmptyWeakMap;
function isEmptyKeys(value) {
if (value == null)
return false;
return Object.keys(value).length === 0;
}
exports.isEmptyKeys = isEmptyKeys;
// -----------------------------------
// General
/**
* The default {@link TypeMap} for {@link getType}.
export * AsyncFunction and SyncFunction are missing, as they are more specific types that people can detect afterwards.
* @readonly
*/
exports.typeMap = Object.freeze({
array: isArray,
boolean: isBoolean,
date: isDate,
error: isError,
class: isClass,
function: isFunction,
null: isNull,
number: isNumber,
regexp: isRegExp,
string: isString,
undefined: isUndefined,
map: isMap,
weakmap: isWeakMap,
object: isObject,
});
/**
* Cycle through the passed {@link TypeMap} testing the value, returning the first type that passes, otherwise `null`.
* @param value the value to test
* @param customTypeMap defaults to {@link typeMap}
*/
function getType(value, customTypeMap) {
if (customTypeMap === void 0) { customTypeMap = exports.typeMap; }
// Cycle through our type map
for (var key in customTypeMap) {
if (customTypeMap.hasOwnProperty(key)) {
if (customTypeMap[key](value)) {
return key;
}
}
}
// No type was successful
return null;
}
exports.getType = getType;