JavaScript's typeof operator is the standard way to ask what kind of value you're holding — but it has well-known holes. typeof null is "object". typeof [] is "object". typeof NaN is "number". You'll build a small library of type-check helpers that paper over those holes so callers get the answer they actually expected.
Implement and export nine helpers from a single module. Each one takes a value and returns a boolean. The full set: isString, isNumber, isBoolean, isArray, isObject, isFunction, isNull, isUndefined, and isNaN. isObject returns true only for plain objects — not arrays, not null. isNumber returns true only for real numbers — NaN does not count as a number here. Use Number.isNaN for the NaN check; the global isNaN coerces its argument first and is not what you want.
function isString(value) { /* returns boolean */ }
function isNumber(value) { /* returns boolean — NaN is NOT a number */ }
function isBoolean(value) { /* returns boolean */ }
function isArray(value) { /* returns boolean */ }
function isObject(value) { /* returns boolean — null and arrays are NOT objects */ }
function isFunction(value) { /* returns boolean */ }
function isNull(value) { /* returns boolean — only for the value null */ }
function isUndefined(value) { /* returns boolean — only for the value undefined */ }
function isNaN(value) { /* returns boolean — only for the NaN value, no coercion */ }
module.exports = {
isString, isNumber, isBoolean, isArray, isObject,
isFunction, isNull, isUndefined, isNaN,
};
isString('hello'); // true
isString(''); // true — empty string is still a string
isString(new String('hi')); // false — boxed wrapper, not a primitive string
isNumber(42); // true
isNumber(NaN); // false — NaN is excluded from "number" here
isNumber('3'); // false — strings that look like numbers don't count
isObject({}); // true
isObject({ a: 1 }); // true
isObject(null); // false — typeof says 'object' but null is its own thing
isObject([1, 2]); // false — arrays get their own helper
isArray([]); // true
isArray([1, 2, 3]); // true
isArray('abc'); // false — strings are iterable, not arrays
isNull(null); // true
isNull(undefined); // false
isUndefined(undefined); // true
isUndefined(null); // false
isNaN(NaN); // true
isNaN('foo'); // false — no coercion (global isNaN would say true)
isNaN(42); // false
typeof for primitives — 'string', 'number', 'boolean', 'function', 'undefined' are all reliably reported by typeof.Array.isArray for arrays — typeof [] is 'object', so typeof alone can't distinguish arrays from plain objects.isObject against null and arrays — typeof null === 'object' is a historical JavaScript bug; you must explicitly reject null and arrays.Number.isNaN, not the global isNaN — global isNaN('foo') returns true because it coerces first. Number.isNaN only returns true for the literal NaN value.Date, Map, Set, class instances all pass isObject here. Distinguishing them is out of scope for v1.