JavaScript / TypeScript Utilities
A collection of light-weight methods and helpers for defensive programming.
Prereqs & Install
Please note that the TypeScript target is ES6.
npm install @usefultools/utils
Usage
There are 6 main modules available:
Async
Available methods:
withTimeout
timeout
makeRecoverable
Examples
withTimeout
The below will resolve source after 750ms.
function findUserById(id: number) {
const source = () => http.get(`/api/users/${id}`)
return withTimeout(source, 750)
}
timeout
The below will reject if asyncOperation takes more than 0.5 seconds.
function work() {
const source = asyncOperation()
return timeout(source, 500)
}
makeRecoverable
The below will retry 5 times.
function getUsers() {
const source = () => http.get("/api/users")
return makeRecoverable(source, 5)
}
The below will retry 3 times, each time with a delay of 250ms.
function getUsers() {
const source = () => http.get("/api/users")
return makeRecoverable(source, 3, 250)
}
The below will retry thrice if the error caught is a SyntaxError
.
function initService() {
const source = () => service.init()
return makeRecoverable(source, 3, 0, SyntaxError)
}
Full test Docs here.
Conditionals
Available methods:
isNull
isUndefined
isMissing
isPresent
isBoolean
isArray
isObject
isString
isNumber
isInteger
isFunction
isNonEmptyString
isNonEmptyArray
isTrue
isFalse
isPositiveInteger
isNonNegativeInteger
hasOneItem
hasMultipleItems
isConstructable
hasOnlyKeys
isEqual
Examples
isNull
Find out whether value is null
isNull(null)
isNull(undefined)
isNull(0)
isNull(NaN)
isUndefined
Find out whether type of value is undefined
isUndefined(undefined)
isUndefined(null)
isUndefined(0)
isMissing
Find out whether value is null or undefined, therefore "missing"
isMissing(null)
isMissing(undefined)
isMissing(0)
isMissing(NaN)
isMissing("")
isPresent
Find out whether value is not null and not undefined, therefore "present"
isPresent(0)
isPresent(NaN)
isPresent("")
isPresent(null)
isPresent(undefined)
isBoolean
Find out whether value is of type Boolean
isBoolean(true)
isBoolean(false)
isBoolean(0)
isArray
Find out whether value is of type Array
isArray([])
isArray([null, undefined])
isArray({})
isObject
Find out whether value is of type Object
isObject({})
isObject(new Function())
isObject([])
isString
Find out whether value is of type String
isString("")
isString(new String())
isNumber
Find out whether value is of type Number
isNumber(42)
isNumber(Math.PI)
isNumber(Infinity)
isNumber(NaN)
isInteger
Find out whether value is of type Number and is an Integer
isInteger(42)
isInteger(Math.PI)
isInteger(Infinity)
isInteger(NaN)
isFunction
Find out whether value is of type Function
isFunction(() => {})
isFunction(ReferenceError)
isFunction(new ReferenceError())
isNonEmptyString
Find out whether value is of type String, and has at least 1 character
isNonEmptyString("Hello, World!")
isNonEmptyString("")
isNonEmptyArray
Find out whether value is of type Array and has at least one element
isNonEmptyArray([null])
isNonEmptyArray([])
isTrue
Find out whether value is of type Boolean and is true
isTrue(true)
isTrue(1)
isTrue(false)
isFalse
Find out whether value is of type Boolean and is false
isFalse(false)
isFalse(0)
isFalse(true)
isPositiveInteger
Find out whether value is an Integer and greater than 0
isPositiveInteger(42)
isPositiveInteger(0)
isPositiveInteger(-42)
isNonNegativeInteger
Find out whether value is an Integer and greater or equal to 0
isNonNegativeInteger(42)
isNonNegativeInteger(0)
isNonNegativeInteger(-42)
hasOneItem
Find out whether value is an Array and its length is 1
hasOneItem([null])
hasOneItem([])
hasOneItem([42, Math.PI])
hasMultipleItems
Find out whether value is an Array and its length is more than 1
hasMultipleItems([42, Infinity])
hasMultipleItems([])
hasMultipleItems(["Hello, World"])
isConstructable
Find out whether value is Constructable
isConstructable(new Function())
isConstructable(function a() {})
isConstructable(class {})
isConstructable(class ClassName {})
isConstructable(() => {})
hasOnlyKeys
Find out whether value has only the keys provided
hasOnlyKeys({ a: "b", c: "d" }, ["a", "c"])
hasOnlyKeys({ a: "b" }, ["a"])
hasOnlyKeys({}, [])
hasOnlyKeys({ a: "b" }, ["c"])
hasOnlyKeys({ a: "b", c: "d" }, ["a"])
isEqual
Find out whether value 1 and value 2 are equal (shallow)
isEqual("Hello, World!", "Hello, World!")
isEqual(null, null)
isEqual(false, false)
isEqual(Math.PI, Math.PI)
isEqual(Infinity, Infinity)
isEqual([], [])
isEqual({}, {})
isEqual(false, true)
Full test Docs here.
Env
Available methods:
getAsBool
getAsInt
getAsStr
NOTE: These methods are namespaced under env
. The usage is therefore
import { env } from "@usefultools/utils"
env.getAsBool(...)
env.getAsInt(...)
env.getAsStr(...)
Examples
Assuming your process.env
has loaded the following .env
.
IS_PROD=true
ASYNC_MAX_TIMEOUT=2500
API_KEY=0351f02f-0be2-49d1-bfed-5c45275d4fd2
env.getAsBool
To retrieve the Boolean value of "IS_PROD"
from process.env
, you can use the following method.
env.getAsBool("IS_PROD")
If the raw value cannot be found, or the parsed value is not a Boolean, this function will throw a ReferenceError
or a TypeError
respectively.
env.getAsInt
To retrieve the Integer value of "ASYNC_MAX_TIMEOUT"
from process.env
, you can use the following method.
env.getAsInt("ASYNC_MAX_TIMEOUT")
If the raw value cannot be found, or the parsed value is not an Integer, this function will throw a ReferenceError
or a TypeError
respectively.
env.getAsStr
To retrieve the String value of "API_KEY"
from process.env
, you can use the following method.
env.getAsStr("API_KEY")
If the raw value cannot be found, this function will throw a ReferenceError
.
In all of the above, you can also use your own env object like so:
env.getAsBool("IS_DEV", env)
Full test Docs here.
Helpers
Available methods:
noop
identity
getRandomIntInclusive
generateId
isValidId
generateUUID
isValidUUID
fill
Examples
noop
Sometimes you might want to provide a default callback parameter to some of your functions to prevent the application from crashing (on the off-chance someone or something accidentally calls them without any parameters). You can use the noop
helper as shown below.
function doSomething(cb = noop) {
let res: string
try {
await http.get("/api/healthcheck")
res = "All works!"
} catch (_err) {
res = "There was an error!"
}
cb(res)
}
identity
Let's assume that doSomething
prints its result (String
) into the console, but applies onSuccess
for a Ok result, and onError
for a Err result. You might want to uppercase the success result, but leave the error message in its original form. You can use the identity helper as shown below.
function onSuccess(res: string) {
return res.toUpperCase()
}
doSomething(onSuccess, identity)
getRandomIntInclusive
To get a random integer within a specified range, you can use the following:
getRandomIntInclusive(10, 99)
generateId
To get a random id (underlying is the shortid
library) use:
generateId()
generateId()
isValidId
To confirm whether a value is a valid id (underlying is the shortid
library) use:
isValidId("HJ5fy5p3G")
isValidId("foo")
generateUUID
To get a random UUID v4 (underlying is the uuid
library) use:
generateUUID()
generateUUID()
isValidId
To confirm whether a value is a valid UUID v4 (underlying is the uuid
library) use:
isValidUUID("1ad006bf-00c0-49de-bcf0-7c5eb2f83241")
isValidUUID("foo")
fill
To fill an array, use:
fill(4)
Full test Docs here.
Match
Available methods:
Other exports:
Examples
match
A basic pattern match:
const getMessage = (year: number): string => match(year)({
[1984]: "The year is 1984.",
[_def]: "Unfortunately, we cannot tell what year it is."
})
getMessage(1984)
getMessage(1994)
getMessage(2024)
Advanced pattern matching, including assertions:
function isFutureYear(year) {
return isPositiveInteger(year)
&& year > new Date().getFullYear()
}
function isCurrentYear(year) {
return isPositiveInteger(year)
&& year === new Date().getFullYear()
}
const getMessage = (year: number): string => match(year)(
[1984, "The year is 1984."],
[isCurrentYear, x => `The year ${x} is up-to-date.`],
[isFutureYear, x => `The year ${x} is in the future...`],
[_def, "Unfortunately, we cannot tell what year it is."],
)
getMessage(1984)
getMessage(2018)
getMessage(2024)
getMessage(1333)
Full test Docs here.
ThrowIf
A collection of simple throwable assertions, all of which throw if the assertion fails.
Available methods:
throwIfMissing
throwIfPresent
throwIfNotBoolean
throwIfNotArray
throwIfNotObject
throwIfNotString
throwIfNotNumber
throwIfNotInteger
throwIfNotFunction
throwIfFalse
throwIfEmptyString
throwIfEmptyArray
throwIfNotPositiveInteger
throwIfNegativeInteger
throwIfNotConstructable
Examples
throwIfNotObject({});
throwIfNotObject([]);
throwIfNotObject(null);
throwIfNotObject(undefined);
You can also provide your own error messages, and errors.
throwIfMissing(someValue, '`someValue` missing!');
throwIfMissing(someValue, '`someValue` missing!', ReferenceError);
Full test Docs here.
Development
- Install dependencies:
npm install
- Compile:
make compile
- Test:
make test
make test-ci
- Format the codebase:
make format
Contributing
If you have comments, complaints, or ideas for improvements, feel free to open an issue or a pull request! See Contributing guide for details about project setup, testing, etc.
Author and license
This library was created by @LITCHI.IO. Main author and maintainer is Slavo Vojacek.
Contributors: Slavo Vojacek
@usefultools/utils
is available under the ISC license. See the LICENSE file for more info.