diff --git a/source/index.ts b/source/index.ts index 4da25b1..b990464 100644 --- a/source/index.ts +++ b/source/index.ts @@ -1,47 +1,91 @@ import * as util from 'util'; -const toString = Object.prototype.toString; -const getObjectType = (value: any) => toString.call(value).slice(8, -1) as string; -const isOfType = (type: string) => (value: any) => typeof value === type; // tslint:disable-line:strict-type-predicates -const isObjectOfType = (type: string) => (value: any) => getObjectType(value) === type; +export const enum TypeName { + null = 'null', + boolean = 'boolean', + undefined = 'undefined', + string = 'string', + number = 'number', + symbol = 'symbol', + Function = 'Function', + Array = 'Array', + Buffer = 'Buffer', + Object = 'Object', + RegExp = 'RegExp', + Date = 'Date', + Error = 'Error', + Map = 'Map', + Set = 'Set', + WeakMap = 'WeakMap', + WeakSet = 'WeakSet', + Int8Array = 'Int8Array', + Uint8Array = 'Uint8Array', + Uint8ClampedArray = 'Uint8ClampedArray', + Int16Array = 'Int16Array', + Uint16Array = 'Uint16Array', + Int32Array = 'Int32Array', + Uint32Array = 'Uint32Array', + Float32Array = 'Float32Array', + Float64Array = 'Float64Array', + ArrayBuffer = 'ArrayBuffer', + SharedArrayBuffer = 'SharedArrayBuffer', + Promise = 'Promise' +} -function is(value: any) { // tslint:disable-line:only-arrow-functions +const toString = Object.prototype.toString; +const isOfType = (type: string) => (value: any) => typeof value === type; // tslint:disable-line:strict-type-predicates + +const getObjectType = (value: any): TypeName | null => { + const objectName = toString.call(value).slice(8, -1) as string; + + if (objectName) { + return objectName as TypeName; + } + + return null; +}; + +const isObjectOfType = (typeName: TypeName) => (value: any) => { + return getObjectType(value) === typeName; +}; + +function is(value: any): TypeName { // tslint:disable-line:only-arrow-functions if (value === null) { - return 'null'; + return TypeName.null; } if (value === true || value === false) { - return 'boolean'; + return TypeName.boolean; } const type = typeof value; if (type === 'undefined') { - return 'undefined'; + return TypeName.undefined; } if (type === 'string') { - return 'string'; + return TypeName.string; } if (type === 'number') { - return 'number'; + return TypeName.number; } if (type === 'symbol') { - return 'symbol'; + return TypeName.symbol; } if (is.function_(value)) { - return 'Function'; + return TypeName.Function; } if (Array.isArray(value)) { - return 'Array'; + return TypeName.Array; } if (Buffer.isBuffer(value)) { - return 'Buffer'; + return TypeName.Buffer; } const tagType = getObjectType(value); @@ -53,7 +97,7 @@ function is(value: any) { // tslint:disable-line:only-arrow-functions throw new TypeError('Please don\'t use object wrappers for primitive types'); } - return 'Object'; + return TypeName.Object; } namespace is { // tslint:disable-line:no-namespace @@ -80,7 +124,7 @@ namespace is { // tslint:disable-line:no-namespace export const iterable = (value: any) => !nullOrUndefined(value) && function_(value[Symbol.iterator]); export const generator = (value: any) => iterable(value) && function_(value.next) && function_(value.throw); - export const nativePromise = isObjectOfType('Promise'); + export const nativePromise = isObjectOfType(TypeName.Promise); const hasPromiseAPI = (value: any) => !null_(value) && @@ -97,26 +141,26 @@ namespace is { // tslint:disable-line:no-namespace export const asyncFunction = isFunctionOfType('AsyncFunction'); export const boundFunction = (value: any) => function_(value) && !value.hasOwnProperty('prototype'); - export const regExp = isObjectOfType('RegExp'); - export const date = isObjectOfType('Date'); - export const error = isObjectOfType('Error'); - export const map = isObjectOfType('Map'); - export const set = isObjectOfType('Set'); - export const weakMap = isObjectOfType('WeakMap'); - export const weakSet = isObjectOfType('WeakSet'); + export const regExp = isObjectOfType(TypeName.RegExp); + export const date = isObjectOfType(TypeName.Date); + export const error = isObjectOfType(TypeName.Error); + export const map = isObjectOfType(TypeName.Map); + export const set = isObjectOfType(TypeName.Set); + export const weakMap = isObjectOfType(TypeName.WeakMap); + export const weakSet = isObjectOfType(TypeName.WeakSet); - export const int8Array = isObjectOfType('Int8Array'); - export const uint8Array = isObjectOfType('Uint8Array'); - export const uint8ClampedArray = isObjectOfType('Uint8ClampedArray'); - export const int16Array = isObjectOfType('Int16Array'); - export const uint16Array = isObjectOfType('Uint16Array'); - export const int32Array = isObjectOfType('Int32Array'); - export const uint32Array = isObjectOfType('Uint32Array'); - export const float32Array = isObjectOfType('Float32Array'); - export const float64Array = isObjectOfType('Float64Array'); + export const int8Array = isObjectOfType(TypeName.Int8Array); + export const uint8Array = isObjectOfType(TypeName.Uint8Array); + export const uint8ClampedArray = isObjectOfType(TypeName.Uint8ClampedArray); + export const int16Array = isObjectOfType(TypeName.Int16Array); + export const uint16Array = isObjectOfType(TypeName.Uint16Array); + export const int32Array = isObjectOfType(TypeName.Int32Array); + export const uint32Array = isObjectOfType(TypeName.Uint32Array); + export const float32Array = isObjectOfType(TypeName.Float32Array); + export const float64Array = isObjectOfType(TypeName.Float64Array); - export const arrayBuffer = isObjectOfType('ArrayBuffer'); - export const sharedArrayBuffer = isObjectOfType('SharedArrayBuffer'); + export const arrayBuffer = isObjectOfType(TypeName.ArrayBuffer); + export const sharedArrayBuffer = isObjectOfType(TypeName.SharedArrayBuffer); export const truthy = (value: any) => Boolean(value); export const falsy = (value: any) => !value; @@ -140,23 +184,31 @@ namespace is { // tslint:disable-line:no-namespace // From: https://github.com/sindresorhus/is-plain-obj/blob/master/index.js let prototype; - return getObjectType(value) === 'Object' && + return getObjectType(value) === TypeName.Object && (prototype = Object.getPrototypeOf(value), prototype === null || // tslint:disable-line:ban-comma-operator prototype === Object.getPrototypeOf({})); }; const typedArrayTypes = new Set([ - 'Int8Array', - 'Uint8Array', - 'Uint8ClampedArray', - 'Int16Array', - 'Uint16Array', - 'Int32Array', - 'Uint32Array', - 'Float32Array', - 'Float64Array' + TypeName.Int8Array, + TypeName.Uint8Array, + TypeName.Uint8ClampedArray, + TypeName.Int16Array, + TypeName.Uint16Array, + TypeName.Int32Array, + TypeName.Uint32Array, + TypeName.Float32Array, + TypeName.Float64Array ]); - export const typedArray = (value: any) => typedArrayTypes.has(getObjectType(value)); + export const typedArray = (value: any) => { + const objectType = getObjectType(value); + + if (objectType === null) { + return false; + } + + return typedArrayTypes.has(objectType); + }; const isValidLength = (value: any) => safeInteger(value) && value > -1; export const arrayLike = (value: any) => !nullOrUndefined(value) && !function_(value) && isValidLength(value.length);