JavaScript strict type checking functions
module.exports = factory | |
function factory() { | |
const exports = { | |
isDef, | |
isUndef, | |
isNull, | |
isBool, | |
isNum, | |
isInt, | |
isStr, | |
isArr, | |
isObj, | |
isPOJO, | |
isFunc, | |
isSymbol | |
} | |
/** | |
*/ | |
function isDef(x) { | |
return !isUndef(x) && !isNull(x) | |
} | |
/** | |
* Does not match: `null` | |
*/ | |
function isUndef(val) { | |
return typeof val === 'undefined' | |
} | |
/** | |
* Does not match: `undefined` | |
*/ | |
function isNull(val) { | |
return val === null | |
} | |
/** | |
*/ | |
function isBool(val) { | |
return typeof val === 'boolean' | |
} | |
/** | |
* Does not match: `NaN`, `Infinity`, `-Infinity` | |
*/ | |
function isNum(val) { | |
return typeof val === 'number' && isFinite(val) | |
} | |
/** | |
* Does not match: `NaN`, `Infinity`, `-Infinity` | |
*/ | |
function isInt(val) { | |
return typeof val === 'number' && isFinite(val) && Math.floor(val) === val | |
} | |
/** | |
*/ | |
function isStr(val) { | |
return typeof val === 'string' | |
} | |
/** | |
*/ | |
function isArr(val) { | |
return Array.isArray(val) | |
} | |
/** | |
* Does not match: arrays, functions, symbols | |
*/ | |
function isObj(val) { | |
return val === Object(val) && !isArr(val) && !isFunc(val) && !isSymbol(val) | |
} | |
/** | |
*/ | |
function isPOJO(x) { | |
return isObj(x) && Object.getPrototypeOf(x) === Object.prototype | |
} | |
/** | |
*/ | |
function isFunc(val) { | |
return typeof val === 'function' | |
} | |
/** | |
*/ | |
function isSymbol(val) { | |
return typeof val === 'symbol' | |
} | |
return exports | |
} |
const factory = require('./type-checks') | |
const types = { | |
undef: [undefined, void 42], | |
nil: [null], | |
bool: [false, true, Boolean()], | |
int: [ | |
0, | |
1, | |
0xbada55, // Base 16: hex | |
0o2471, // Base 8: octal, | |
Number.MAX_SAFE_INTEGER | |
], | |
num: [ | |
1.01, | |
0.30000000000000004 // 0.1 + 0.2 | |
], | |
specialNum: [NaN, Infinity, -Infinity], | |
str: ['', String(), String(''), String('abc'), 'latin', '日本語'], | |
arr: [ | |
[], | |
[1, 'two'], | |
Array(3), // [ <3 empty items> ] | |
[null, undefined], | |
new (class A extends Array {})() // [] | |
], | |
obj: [ | |
new (class A {})(), | |
new (function Foo() {})(), | |
Object.prototype, | |
Object.create(null), | |
Object.create({}), | |
new Date(), | |
new RegExp() | |
], | |
pojo: [ | |
{}, | |
Object(), | |
new Object(), | |
Object.create(Object.prototype), | |
{ length: 0 }, // Not an array | |
{ length: 2, '0': 42 }, // Not an array | |
{ answer: 42 } | |
], | |
sym: [Symbol(), Symbol('label')], | |
fun: [ | |
() => 0, | |
function() {}, | |
function named() {}, | |
Function(), | |
parseInt, | |
Symbol // Function | |
] | |
} | |
describe('type checks', () => { | |
it('isDef()', () => { | |
const { isDef } = factory() | |
const match = [].concat( | |
types.bool, | |
types.int, | |
types.num, | |
types.specialNum, | |
types.str, | |
types.arr, | |
types.obj, | |
types.pojo, | |
types.sym, | |
types.fun | |
) | |
const nomatch = [].concat(types.undef, types.nil) | |
match.forEach(val => { | |
if (!isDef(val)) throw val | |
}) | |
nomatch.forEach(val => { | |
if (isDef(val)) throw val | |
}) | |
}) | |
it('isUndef()', () => { | |
const { isUndef } = factory() | |
const match = types.undef | |
const nomatch = [].concat( | |
types.nil, | |
types.bool, | |
types.int, | |
types.num, | |
types.specialNum, | |
types.str, | |
types.arr, | |
types.obj, | |
types.pojo, | |
types.sym, | |
types.fun | |
) | |
match.forEach(val => { | |
if (!isUndef(val)) throw val | |
}) | |
nomatch.forEach(val => { | |
if (isUndef(val)) throw val | |
}) | |
}) | |
it('isNull()', () => { | |
const { isNull } = factory() | |
const match = types.nil | |
const nomatch = [].concat( | |
types.undef, | |
types.bool, | |
types.int, | |
types.num, | |
types.specialNum, | |
types.str, | |
types.arr, | |
types.obj, | |
types.pojo, | |
types.sym, | |
types.fun | |
) | |
match.forEach(val => { | |
if (!isNull(val)) throw val | |
}) | |
nomatch.forEach(val => { | |
if (isNull(val)) throw val | |
}) | |
}) | |
it('isBool()', () => { | |
const { isBool } = factory() | |
const match = types.bool | |
const nomatch = [].concat( | |
types.undef, | |
types.nil, | |
types.int, | |
types.num, | |
types.specialNum, | |
types.str, | |
types.arr, | |
types.obj, | |
types.pojo, | |
types.sym, | |
types.fun | |
) | |
match.forEach(val => { | |
if (!isBool(val)) throw val | |
}) | |
nomatch.forEach(val => { | |
if (isBool(val)) throw val | |
}) | |
}) | |
it('isNum()', () => { | |
const { isNum } = factory() | |
const match = [].concat(types.int, types.num) | |
const nomatch = [].concat( | |
types.undef, | |
types.nil, | |
types.bool, | |
types.specialNum, | |
types.str, | |
types.arr, | |
types.obj, | |
types.pojo, | |
types.sym, | |
types.fun | |
) | |
match.forEach(val => { | |
if (!isNum(val)) throw val | |
}) | |
nomatch.forEach(val => { | |
if (isNum(val)) throw val | |
}) | |
}) | |
it('isInt()', () => { | |
const { isInt } = factory() | |
const match = [].concat(types.int) | |
const nomatch = [].concat( | |
types.undef, | |
types.nil, | |
types.bool, | |
types.num, | |
types.specialNum, | |
types.str, | |
types.arr, | |
types.obj, | |
types.pojo, | |
types.sym, | |
types.fun | |
) | |
match.forEach(val => { | |
if (!isInt(val)) throw val | |
}) | |
nomatch.forEach(val => { | |
if (isInt(val)) throw val | |
}) | |
}) | |
it('isStr()', () => { | |
const { isStr } = factory() | |
const match = types.str | |
const nomatch = [].concat( | |
types.undef, | |
types.nil, | |
types.bool, | |
types.int, | |
types.num, | |
types.specialNum, | |
types.arr, | |
types.obj, | |
types.pojo, | |
types.sym, | |
types.fun | |
) | |
match.forEach(val => { | |
if (!isStr(val)) throw val | |
}) | |
nomatch.forEach(val => { | |
if (isStr(val)) throw val | |
}) | |
}) | |
it('isArr()', () => { | |
const { isArr } = factory() | |
const match = types.arr | |
const nomatch = [].concat( | |
types.undef, | |
types.nil, | |
types.bool, | |
types.int, | |
types.num, | |
types.specialNum, | |
types.str, | |
types.obj, | |
types.pojo, | |
types.sym, | |
types.fun | |
) | |
match.forEach(val => { | |
if (!isArr(val)) throw val | |
}) | |
nomatch.forEach(val => { | |
if (isArr(val)) throw val | |
}) | |
}) | |
it('isObj()', () => { | |
const { isObj } = factory() | |
const match = [].concat(types.obj, types.pojo) | |
const nomatch = [].concat( | |
types.undef, | |
types.nil, | |
types.bool, | |
types.int, | |
types.num, | |
types.specialNum, | |
types.str, | |
types.arr, | |
types.sym, | |
types.fun | |
) | |
match.forEach(val => { | |
if (!isObj(val)) throw val | |
}) | |
nomatch.forEach(val => { | |
if (isObj(val)) throw val | |
}) | |
}) | |
it('isPOJO()', () => { | |
const { isPOJO } = factory() | |
const match = types.pojo | |
const nomatch = [].concat( | |
types.undef, | |
types.nil, | |
types.bool, | |
types.int, | |
types.num, | |
types.specialNum, | |
types.str, | |
types.arr, | |
types.obj, | |
types.sym, | |
types.fun | |
) | |
match.forEach(val => { | |
if (!isPOJO(val)) throw val | |
}) | |
nomatch.forEach(val => { | |
if (isPOJO(val)) throw val | |
}) | |
}) | |
it('isFunc()', () => { | |
const { isFunc } = factory() | |
const match = types.fun | |
const nomatch = [].concat( | |
types.undef, | |
types.nil, | |
types.bool, | |
types.int, | |
types.num, | |
types.specialNum, | |
types.str, | |
types.arr, | |
types.obj, | |
types.pojo, | |
types.sym | |
) | |
match.forEach(val => { | |
if (!isFunc(val)) throw val | |
}) | |
nomatch.forEach(val => { | |
if (isFunc(val)) throw val | |
}) | |
}) | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment