Assertions
Functions for testing the type of a value.
Most of these are trivially simple functions that are already one-liners. I find it easier to write (and read) isBoolean(foo)
than typeof foo === 'boolean'
.
isBoolean(value)
Determines if a value is a boolean. Returns true
if the value is true
or false
. Otherwise it returns false.
isBoolean(true); // true
isBoolean(false); // true
isBoolean(1); // false
isBoolean(0); // false
Values that can be coerced to boolean values (e.g. the numbers 0
and 1
) are not considered booleans and the function will return false
.
isString(value)
Determines if a value is a string. Returns Boolean true
or false
.
isString('Hello World'); // true
isString(42); // false
isNumber(value)
Determines if a value is a number. Returns Boolean true
or false
.
isNumber(42); // true
isNumber(42.43); // true
isNumber("42"); // false
isInteger(value)
Determines if a value is an integer. Returns Boolean true
or false
.
isInteger(42); // true
isInteger(42.0); // true
isInteger(42.43); // false
isInteger("42"); // false
Note that numbers with decimal parts that are zero (e.g. 42.0
) are considered to be integers.
isFloat(value)
Determines if a value is a floating point number. Returns Boolean true
or false
.
isFloat(42); // false
isFloat(42.0); // false
isFloat(42.43); // true
isFloat("42"); // false
Note that numbers with decimal parts that are zero (e.g. 42.0
) are considered to be integers and the function will return false
in those cases.
isArray(value)
Determines if a value is an array. Returns Boolean true
or false
.
isArray([42, 43]); // true
isArray("42, 43"); // false
isFunction(value)
Determines if a value is a function. Returns Boolean true
or false
.
isFunction( a => a + 1 ); // true
isFunction("badger badger"); // false
If you're using Typescript you can use a type generic to narrow the type of the function assertion. In this example we use isFunction<ReturnNumber>
. When the function returns true
, it establishes that a
is not only a function, but also has the type of ReturnNumber
and can safely be called as a(10)
.
type ReturnNumber = (n: number) => number
const addOne: ReturnNumber = n => n + 1
const someNumber = (a: number | ReturnNumber): number =>
isFunction<ReturnNumber>(a)
? a(10)
: a
someNumber(10) // => 10
someNumber(addOne) // => 11
isRegExp(value)
Determines if a value is a RegExp object. Returns Boolean true
or false
.
isRegExp(/badger/); // true
isRegExp("badger badger"); // false
isObject(value)
Determines if a value is an object.
Javascript's concept of an object is ambiguous because a number of different data types are considered to be objects, including Array
and null
. This function will return false
for arrays and null values and only return true
for values that are objects in the more traditional sense: an instance of a class (e.g. new Date()
) or a data structure created with curly braces (e.g. { b: 'badger' }
).
Returns Boolean true
or false
.
isObject(new Date()); // true
isObject({ b: 'badger' }); // true
isObject([10, 20]); // false
isObject(null); // false
isSimple(value)
Determines if a value is a "simple" scalar value, e.g. a string, number or boolean value.
isSimple('eleven'); // true
isSimple(11); // true
isSimple(11.0); // true
isSimple(true); // true
isSimple(false); // true
isSimple({ }); // false
isSimple([ ]); // false
isSimple(null); // false
isUndefined(value)
Determines if a value has the undefined
value. Returns Boolean true
or false
.
Note that this does not include null
. Use hasValue(value)
or noValue(value)
to test for a value being either undefined
or null
.
isUndefined(undefined); // true
isUndefined(null); // false
isUndefined(0); // false
isNull(value)
Determines if a value has the null
value. Returns Boolean true
or false
.
Note that this does not include undefined
values. Use hasValue(value)
or noValue(value)
to test for a value being either undefined
or null
.
isNull(null); // true
isNull(undefined); // false
isNull(0); // false
isEmpty(value)
Determines if an array or object value is empty. For an array it's equivalent to value.length === 0
. For an object it's Object.keys(value).length === 0
. Returns Boolean true
or false
.
isEmpty([ ]) // true
isEmpty({ }) // true
isEmpty([ 10 ]) // false
isEmpty({ a: 10 }) // false
hasValue(value)
Determines if a value has a defined and non-null value. Returns Boolean true
or false
.
Note that this is subtly different from Javascript's idea of truth. This function will return true
if the value is a boolean false
or the number 0
. However, it is the same as Javascript's Nullish coalescing operator??
which returns the right operand when the left operand is null
or undefined
.
hasValue(0); // true
hasValue(false); // true
hasValue(null); // false
hasValue(undefined); // false
noValue(value)
Determines if a value does not have a defined and non-null value. It is the logical negation of hasValue()
. Returns Boolean true
or false
.
noValue(null); // true
noValue(undefined); // true
noValue(0); // true
noValue(false); // true
hasValues(values)
Determines if all the elements in an array have defined and non-null value (via hasValue()
). Returns Boolean true
or false
.
hasValues([0, 1, 2]); // true
hasValues([0, 1, null]); // false
hasValues([0, 1, undefined]); // false
haveValue(...values)
Determines if all the values passed as arguments have defined and non-null value (via hasValue()
). Returns Boolean true
or false
.
haveValue(0, 1, 2); // true
haveValue(0, 1, null); // false
haveValue(0, 1, undefined); // false
Note the subtle difference between this function which checks all the arguments passed, and hasValues()
which checks all the elements in a single array.
If you're using Typescript then the hasValues()
is probably the better choice.
Consider this example. The type for the a
parameter is an array of elements which can be numbers, null or undefined values. The hasValues(a)
function asserts that all elements in a
are NOT null or undefined. Typescript can then infer that it must be an array of numbers and thus, it's safe to run the a.reduce(...)
code to sum them.
function addSomeNumbers(a: Array<number | null | undefined>): number {
return hasValues(a)
? a.reduce( // Typescript can infer that a must be an
(sum, n) => sum + n, // array of numbers because hasValues(s)
0 // asserts that, so it's safe to sum them
)
: 42
}
When using haveValue()
, Typescript can't make that inference so you'll need to provide additional assertions to reassure it that you know what you're doing.
In this example, we can see that if haveValue(a, b)
returns true then a
and b
must both be numbers and it's safe to add them together. However, Typescript can't infer that so you must add the as number
type assertion when adding a
to b
.
function addTwoNumbers(
a: number | null | undefined,
b: number | null | undefined,
): number {
return haveValue(a, b)
? (a as number) + (b as number)
: 42
}
firstValue(...values)
Returns the first argument that has a defined and non-null value, tested using hasValue()
.
firstValues(0, 1, 2); // 0
firstValues(undefined, 1, 2); // 1
firstValues(null, 2, 3); // 2
firstValues(false, 3, 4); // false
If you're using Typescript then you can add a generic type which will assert that the return value either has this type or is undefined
.
Typescript is smart enough to infer the type from the first argument that isn't null
or undefined
. In this example it's safe to set the type of a
to number | undefined
.
const a: number | undefined = firstValue(
null, 1, 2, 3, undefined
)
However if the arguments contained mixed types then you'll need give Typescript a hint about what types the arguments can safely have. In this example we use the number|string
generic type on firstValue
to do that.
const a: number | string | undefined = firstValue<number|string>(
null, 1, 'two', 3, undefined
)