A collection of some of my most used JavaScript / TypeScript utility functions.
- 🌴 - Three-shakable ESM modules.
- 💬 - Fully typed TSDocs with examples
- 📁 - Small size
- 🔖 - Own well-tested utilities or imported from large open source projects.
# npm
npm install @banjoanton/utils
# yarn
yarn add @banjoanton/utils
# pnpm
pnpm install @banjoanton/utilsimport{invariant,debounce}from"@banjoanton/utils";// orconst{ invariant, debounce }=require("@banjoanton/utils");Auto generated from TSDocs.
- Array
- Base
- Cache
- Crypto
- Date
- Function
- Is
- Number
- Object
- Result
- result.isOk
- result.isErr
- result.map
- result.mapErr
- result.tap
- result.tapErr
- result.andThen
- result.match
- result.unwrap
- result.unwrapOr
- result.mapAsync
- result.mapErrAsync
- result.tapAsync
- result.tapErrAsync
- result.andThenAsync
- tryResult
- Result.ok
- Result.err
- Result.isResult
- Result.tryAsync
- Result.fromNullable
- Result.all
- Result.fromThrowable
- Result.fromAsyncThrowable
- createResult
- Simple-result
- String
- Test
Utility functions for working with arrays.
Convert a single value or array of values into an array.
toArray(1);// returns [1]toArray([1,2,3]);// returns [1, 2, 3]Take the first n elements of an array.
take([1,2,3,4,5],2);// returns [1, 2]take(["a","b","c","d","e"],3);// returns ['a', 'b', 'c']Remove duplicate values from an array. Primites works as usual, objects are compared by value.
uniq([1,2,2,3,4,4]);// returns [1, 2, 3, 4]uniq(["a","a","b","c"]);// returns ['a', 'b', 'c']// objects are compared by valueconsta={name: "Alex",age: 20};constb={name: "Alex",age: 15};constc={name: "Bony",age: 5};constd={name: "Bony",age: 5};uniq([a,b,c,d]);// returns [a, b, c]Remove duplicate values from an array by a key. Can also take a custom function that receives the item to choose the value to compare by.
consta={name: "Alex",age: 20};constb={name: "Alex",age: 15};// compare by a single keyuniqBy([a,b],"name");// returns [a]uniqBy([a,b],"age");// returns [a, b]// compare by a custom functionuniqBy([a,b],item=>item.name);// returns [a]uniqBy([a,b],item=>item.age);// returns [a, b]Shuffle the elements of an array. Creates a new array with the elements of the original array in a random order.
shuffle([1,2,3,4,5]);// returns [2, 4, 1, 5, 3]shuffle(["a","b","c","d","e"]);// returns ['b', 'd', 'a', 'e', 'c']Create a chunk of an array. A chunk is a new array containing a specified number of elements from the original array.
chunk([1,2,3,4,5],2);// returns [[1, 2], [3, 4], [5]]chunk(["a","b","c","d","e"],3);// returns [['a', 'b', 'c'], ['d', 'e']]chunk([1,2,3,4,5],10);// returns [[1, 2, 3, 4, 5]]chunk([1,2,3,4,5],1);// returns [[1], [2], [3], [4], [5]]chunk([1,2,3,4,5],0);// returns []Return the last element of an array.
last([1,2,3]);// returns 3last(["a","b","c"]);// returns 'c'Return the first element of an array.
first([1,2,3]);// returns 1first(["a","b","c"]);// returns 'a'Generate an array of numbers in a given range.
range(5);// returns [0, 1, 2, 3, 4]range(2,5);// returns [2, 3, 4]range(2,10,2);// returns [2, 4, 6, 8]Move an element of an array from one position to another.
move([1,2,3,4],0,2);// returns [2, 3, 1, 4]move(["a","b","c","d"],1,3);// returns ['a', 'c', 'd', 'b']Return a random element from an array.
sample([1,2,3,4]);// returns a random element from the arraysample(["a","b","c","d"]);// returns a random element from the arrayRemove one or more elements from an array. Either by item or by predicate.
remove([1,2,3,4],2);// returns [1, 3, 4]remove(["a","b","c","d"],"b");// returns ['a', 'c', 'd']// remove by a custom functionremove([1,2,3],item=>item===2);// returns [1, 3]remove(["a","b","c","d"],item=>item==="b");// returns ['a', 'c', 'd']Remove falsy values (
null,undefined,"",0,false,NaN) from an array.
compact([1,2,3,4,0,null,undefined,false]);// returns [1, 2, 3, 4]Return the difference between two arrays. Objects are compared by value, meaning that two objects with the same properties will be considered equal. Can also take a custom comparator function.
// primitives are compared by valuedifference([1,2,3,4],[2,4]);// returns [1, 3]difference(["a","b","c","d"],["b","d"]);// returns ['a', 'c']// objects are also compared by value by defaultconstobj={};difference([obj],[obj]);// returns []difference([{a: 1}],[{a: 1}]);// returns []difference([{a: 1}],[{a: 2}]);// returns [{ a: 1 }]// custom comparatorconstcomparator=(a: any,b: any)=>a===b;difference([1,2,3,4],[2,4],comparator);// returns [1, 3]difference(["a","b","c","d"],["b","d"],comparator);// returns ['a', 'c']Return the intersection between two arrays. Objects are compared by value, meaning that two objects with the same properties will be considered equal. Can also take a custom comparator function.
// primitives are compared by valueintersection([1,2,3,4],[2,4]);// returns [2, 4]intersection(["a","b","c","d"],["b","d"]);// returns ['b', 'd']intersection([1,2,3,4],[2,4,5]);// returns [2, 4]// objects are also compared by value by defaultconstobj={};intersection([obj],[obj]);// returns [obj]intersection([{a: 1}],[{a: 1}]);// returns [{ a: 1 }]intersection([{a: 1}],[{a: 2}]);// returns []// custom comparatorconstcomparator=(a: any,b: any)=>a===b;intersection([1,2,3,4],[2,4],comparator);// returns [2, 4]intersection(["a","b","c","d"],["b","d"],comparator);// returns ['b', 'd']Union multiple arrays. Objects are compared by value, meaning that two objects with the same properties will be considered equal.
union([1,2,3],[2,4]);// returns [1, 2, 3, 4]union(["a","b","c"],["b","d"]);// returns ['a', 'b', 'c', 'd']// multiple arraysunion([1,2,3],[2,4],[5,6]);// returns [1, 2, 3, 4, 5, 6]// objects are also compared by value by defaultconstpoint1={x: 1,y: 1};constpoint2={x: 2,y: 2};constpoint3={x: 3,y: 3};constpoint3ButSame={x: 3,y: 3};union([point1,point2],[point2,point3],[point3ButSame]);// returns [point1, point2, point3]Sort an array. Can sort by a single key or multiple keys. Can also take a custom function that receives the item to choose the value to sort by.
consta={name: "Alex",age: 20};constb={name: "Alex",age: 15};constc={name: "Bony",age: 5};// sort by a single keysortBy([a,b,c],"name");// returns [a, b, c]sortBy([a,b,c],"age");// returns [c, b, a]// sort by multiple keyssortBy([a,b,c],["name","age"]);// returns [b, a, c]// sort by a custom functionsortBy([a,b,c],item=>item.name);// returns [a, b, c]sortBy([a,b,c],item=>item.age);// returns [c, b, a]Group an array by a key. Can also take a custom function that receives the item to choose the value to group by.
consta={name: "Alex",age: 20};constb={name: "Alex",age: 15};constc={name: "Bony",age: 5};groupBy([a,b,c],"name");// returns {Alex: [a, b], Bony: [c]}groupBy([a,b,c],"age");// returns {5: [c], 15: [b], 20: [a]}groupBy([a,b,c],item=>item.name);// returns {Alex: [a, b], Bony: [c]}groupBy([a,b,c],item=>item.age);// returns {5: [c], 15: [b], 20: [a]}Creates an object composed of keys generated from the results of running each element of the array through the given key. The key can be a property name (must be a key of T) or a function that returns a key for each item. If multiple items produce the same key, the last one will be used.
typeUser={id: number;name: string};constusers: User[]=[{id: 1,name: "Alice"},{id: 2,name: "Bob"},];keyBy(users,"id");// returns { "1": { id: 1, name: "Alice" }, "2": { id: 2, name: "Bob" } }keyBy(users,user=>user.name);// returns { "Alice": { id: 1, name: "Alice" }, "Bob": { id: 2, name: "Bob" } }Type guard to check if a value is included in an array. Useful for filtering arrays.
constvalues=["a","b","c"]asconst;constvalueToCheck: unknown="a";includes(values,valueToCheck);// returns trueif(includes(values,valueToCheck)){// valueToCheck is now of type "a" | "b" | "c"}Zip multiple arrays into a single array of arrays. The first element of the result array will contain the first element of all the input arrays, the second element of the result array will contain the second element of all the input arrays, and so on.
zip([1,2,3],[4,5,6]);// returns [[1, 4], [2, 5], [3, 6]]zip([1,2,3],["a","b","c"]);// returns [[1, "a"], [2, "b"], [3, "c"]]Partition an array into two arrays. The first array will contain the items that pass the predicate function, the second array will contain the items that don't pass the predicate function.
consta={name: "Alex",age: 20};constb={name: "Alex",age: 15};partition([a,b],item=>item.age>18);// returns [[a], [b]]constvalues=[1,2,3,4,5];partition(values,item=>item%2===0);// returns [[2, 4], [1, 3, 5]]Return the sum of all the elements in an array.
sum([1,2,3,4,5]);// returns 15Base utilities that have no particular classification.
Sleep for a given amount of time.
awaitsleep(1000);// sleep for 1 secondawaitsleep();// sleep for at least 0 millisecondsCache utility.
Creates a super simple cache with expiration and support for persistence in browsers. Can be used with strings and symbols as key. Is generic and can be used with any type.
const{ get, set, has, delete, clear }=createCache();set("key","value");get("key");// "value"has("key");// truedelete("key");// trueclear();// can be used with genericsconstcache=createCache<string>();// can be used with symbolsconstcache=cache();constkey=Symbol("key");cache.set(key,"value");// can be be persisted in local storageconstcache=createCache({persistent: true});// can be be persisted in local storage with a custom keyconstcache=createCache({persistent: true,key: "my-cache"});// custom expiration time in msconstcache=createCache({ttl: 1000});// without expiration timeconstcache=createCache({ttl: false});Utility functions for crypto.
Create a new UUID. Based on the "uncrypto" library.
uuid();// returns a random UUIDuuid();// returns another random UUIDChecks if a string is a valid UUID.
isUUID("hello world");// returns falseisUUID("9cea4ab2-beb8-4b02-ab10-48a39c6b91fa");// returns trueEncrypt a string with a key. Based on the "uncrypto" library. Uses AES-CBC with a random IV. Returns a string with the IV prepended. Use decrypt to decrypt the string.
awaitencrypt("hello world","key");// returns "IV:encryptedData"Decrypt a string with a key. Based on the "uncrypto" library. Expects a string in the format of "IV:encryptedData" in base64 format. Use encrypt to encrypt a string.
awaitdecrypt("IV:encryptedData","key");// returns "hello world"Hash an object or string with SHA-256. From the
ohashlibrary.
awaithash("hello world");// returns "hashedString"awaithash({foo: "bar"});// returns "hashedString"awaithash({foo: "bar"});// returns the same "hashedString" as beforeUtility functions for date and time.
Returns an array of month names. The array is zero-based, so the first month is January.
getCalendarMonths();// returns ['January', 'February', ...]getCalendarMonths({month: "short"});// returns ['Jan', 'Feb', ...]getCalendarMonths({month: "narrow"});// returns ['J', 'F', ...]getCalendarMonths({month: "numeric"});// returns ['1', '2', ...]getCalendarMonths({locales: "fr-FR"});// returns ['janvier', 'février', ...]getCalendarMonths({locales: "sv-SE"});// returns ['januari', 'februari', ...]Returns an array of day names. The array is zero-based. The first day is Monday by default.
getCalendarDays();// returns ['Monday', 'Tuesday', ...]getCalendarDays({day: "short"});// returns ['Mon', 'Tue', ...]getCalendarDays({day: "narrow"});// returns ['M', 'T', ...]getCalendarDays({startOnMonday: false});// returns ['Sunday', 'Monday', ...]getCalendarDays({locales: "fr-FR"});// returns ['lundi', 'mardi', ...]getCalendarDays({locales: "sv-SE"});// returns ['måndag', 'tisdag', ...]getCalendarDays({locales: "sv-SE",startOnMonday: false});// returns ['söndag', 'måndag', ...]Converts a time unit to milliseconds. Combine all units to get the total time in milliseconds.
toMilliseconds({seconds: 10});// returns 10000toMilliseconds({minutes: 10});// returns 600000toMilliseconds({hours: 10});// returns 36000000toMilliseconds({seconds: 10,minutes: 10});// returns 610000toMilliseconds({seconds: 10,minutes: 10,hours: 10});// returns 36610000Converts a time unit to seconds. Combine all units to get the total time in seconds.
toSeconds({seconds: 10});// returns 10toSeconds({minutes: 10});// returns 600toSeconds({hours: 10});// returns 36000toSeconds({days: 10});// returns 864000Converts a time unit to minutes. Combine all units to get the total time in minutes.
toMinutes({seconds: 10});// returns 0.16666666666666666toMinutes({minutes: 10});// returns 10toMinutes({hours: 10});// returns 600toMinutes({days: 10});// returns 14400Converts a time unit to hours. Combine all units to get the total time in hours.
toHours({seconds: 10});// returns 0.002777777777777778toHours({minutes: 10});// returns 0.16666666666666666toHours({hours: 10});// returns 10toHours({days: 10});// returns 240Converts a time unit to days. Combine all units to get the total time in days.
toDays({seconds: 10});// returns 0.00011574074074074074toDays({minutes: 10});// returns 0.006944444444444444toDays({hours: 10});// returns 0.4166666666666667toDays({days: 10});// returns 10Returns the earliest date in an array of dates.
earliest([...dates]);constearlyDate=newDate(2020,0,1);constlateDate=newDate(2020,0,2);earliest([earlyDate,lateDate]);// returns earlyDateReturns the latest date in an array of dates.
latest([...dates]);constearlyDate=newDate(2020,0,1);constlateDate=newDate(2020,0,2);latest([earlyDate,lateDate]);// returns lateDateReturns true if a date is between two other dates.
isBetweenDates([...dates]);constearlyDate=newDate(2020,0,1);constdateInBetween=newDate(2020,0,2);constlateDate=newDate(2020,0,3);isBetweenDates(dateInBetween,earlyDate,lateDate);// returns trueFormat date to ISO 8601 format. YYYY-MM-DD.
toIsoDateString(newDate(2020,0,1));// returns '2020-01-01'Get the first day (monday) of the week. Defaults to today if nothing is passed.
getFirstDayOfWeek();// returns previous mondaygetFirstDayOfWeek(newDate("2022-02-02"));// returns previous monday from specified dateGet the week number of the specified date. Defaults to today. Wrapper around "current-week-number".
getWeekNumber();// returns 5 (if in week 5)getWeekNumber("2020-01-04");// returns 1Parse a date string or date object to a Date object based on the provided options. If a Date object is passed, it is returned as is. If throws is true and the date is invalid, it throws an error. If throws is false and the date is invalid, it returns undefined. This is the default behavior.
parseDate("2020-01-01");// returns Date object or returns undefined if invalidparseDate("2020-01-01",{throws: true});// returns Date object or throws error if invalidparseDate(newDate("2020-01-01"));// returns Date objectparseDate(123456789,{throws: true});// throws errorparseDate({},{throws: false});// returns undefinedparseDate([],{throws: false});// returns undefinedUtilities for working with functions.
Created a debounced version of the provided function. The function is a wrapper around the "throttle-debounce" library.
constdebounced=debounce(()=>console.log("hello world"),1000);debounced();// logs 'hello world' after 1000msdebounced();// does nothing if called within 1000ms of the previous callCreated a throttled version of the provided function. The function is a wrapper around the "throttle-debounce" library.
// invokes the function not more than once per secondconstthrottled=throttle(()=>console.log("hello world"),1000);element.addEventListener("mousemove",throttled);// cancel the throttled functionthrottled.cancel();Invoke all functions in an array. Will not invoke any functions that are undefined.
batchInvoke([()=>console.log("hello"),()=>console.log("world")]);// logs 'hello' and 'world'batchInvoke([()=>console.log("hello"),undefined,()=>console.log("world")]);// logs 'hello' and 'world'A no-op function. Useful for default values.
noop();// does nothingconstmyFunction=(callback=noop)=>{callback();};myFunction();// does nothingconstfunc=noop;func();// does nothingA no-op async function. Useful for default values.
noopAsync();// does nothingconstmyFunction=async(callback=noopAsync)=>{awaitcallback();};awaitmyFunction();// does nothingCreates a function that memoizes the result of
fn. Iffnis called multiple times with the same arguments, the cached result for that set of arguments is returned.
constadd=(a: number,b: number)=>a+b;constmemoizedAdd=memoize(add);memoizedAdd(1,2);// returns 3 and caches the resultmemoizedAdd(1,2);// returns 3 from the cachememoizedAdd(1,2);// returns 3 from the cachememoizedAdd(1,3);// returns 4 and caches the resultmemoizedAdd(1,3);// returns 4 from the cacheCreates a function that raises and error with the provided message. Makes it a bit easier to use in some cases.
raise("Something went wrong");constdata=somethingThatMightExist??raise("Data does not exist");Check that a value is of type never. Useful for checking that a switch statement is exhaustive in TypeScript.
typeFoo="a"|"b";switch(foo){case"a":
// do somethingbreak;default:
exhaustiveCheck(foo);// raises an error}Check that a value is not falsy. Useful for narrowing types in TypeScript.
constperson: Person|undefined=getPerson();invariant(person,"Person does not exist");// person is now of type Person if it existsconstperson: Person|undefined=undefined;invariant(person,"Person does not exist");// raises an errorProduce a new object from an existing object without mutating the original object. Uses structured cloning to create a deep clone of the object. Works with non-primitive types like arrays, maps, sets and objects. A simple version of immer.
// original versionconstperson={name: "John",age: 30};constupdatedPerson=produce(person,draft=>{draft.age=31;});console.log(person.age);// 30console.log(updatedPerson.age);// 31// curried versionconstproducePerson=produce((draft: Person)=>{draft.age=31;});constperson={name: "John",age: 30};constupdatedPerson=producePerson(person);console.log(person.age);// 30console.log(updatedPerson.age);// 31// curried version in Reactconst[person,setPerson]=useState({name: "John",age: 30});setPerson(produce(draft=>{draft.age=31;}));Utility functions for checking the type of a value.
Check if the given value is a boolean.
isBoolean(true);// trueisBoolean("hello world");// falseCheck if the given value is a number. NaN is not considered a number. A string containing a number is not considered a number.
isNumber(1);// trueisNumber("hello world");// falseisNumber(NaN);// falseCheck if the given value is a string.
isString("hello world");// trueisString(1);// falseCheck if the given value is a symbol.
isSymbol(Symbol("hello world"));// trueisSymbol("hello world");// falseCheck if the given value is a function.
isFunction(()=>{});// trueisFunction("hello world");// falseisFunction(1);// falseCheck if the given value is an object.
isObject({});// trueisObject("hello world");// falseisObject(1);// falseCheck if the given value is a Date object. Cannot be used to check if a value is a valid date.
isDateObject(newDate());// trueisDateObject("hello world");// falseisDateObject(1);// falseisDateObject(newDate("hello world"));// trueCheck if the given value is a valid date. Cannot be used to check if a value is a Date object. Can pass strings, numbers, or Date objects. Notice that dates might works differently in different browsers. Passing in "1" will return true in Chrome, but false in Firefox.
isDate(newDate());// trueisDate("hello world");// falseisDate(1);// true or false depending on the browserisDate(newDate("hello world"));// falseisDate("2022-12-24");// trueCheck if the given value is a RegExp.
isRegExp(/helloworld/);// trueisRegExp("hello world");// falseisRegExp(1);// falseisRegExp(newRegExp("hello world"));// trueCheck if the given value is null.
isNull(null);// trueisNull("hello world");// falseisNull(1);// falseisNull(undefined);// falseCheck if the given value is undefined.
isUndefined(undefined);// trueisUndefined("hello world");// falseisUndefined(1);// falseisUndefined(null);// falseCheck if the given value is null or undefined.
isNullish(null);// trueisNullish(undefined);// trueisNullish("hello world");// falseisNullish(1);// falseCheck if the given value is null or undefined.
Deprecated: Use isNullish instead.
isNil(null);// trueisNil(undefined);// trueisNil("hello world");// falseisNil(1);// falseCheck if the given value exists (is not undefined). Also type guards against undefined.
isDefined(undefined);// falseisDefined(null);// trueisDefined("hello world");// trueisDefined(1);// trueisDefined(false);// trueisDefined([]);// trueCheck if the given value is not null or undefined. Also type guards against null and undefined.
exists(undefined);// falseexists(null);// falseexists("hello world");// trueexists(1);// trueexists(false);// trueexists([]);// trueCheck if the given value is truthy. Also type guards against falsy values.
isTruthy(undefined);// falseisTruthy(null);// falseisTruthy("hello world");// trueisTruthy(1);// trueisTruthy(false);// falseisTruthy([]);// trueisTruthy(0);// falseisTruthy("");// falseisTruthy(NaN);// falseisTruthy({});// trueCheck if the given value is falsy. Also type guards against truthy values.
isFalsy(undefined);// trueisFalsy(null);// trueisFalsy("hello world");// falseisFalsy(1);// falseisFalsy(false);// trueisFalsy([]);// falseisFalsy(0);// trueisFalsy("");// trueisFalsy(NaN);// trueisFalsy({});// falseCheck if the given value is a primitive type (string, number, boolean).
isPrimitive("hello world");// trueisPrimitive(1);// trueisPrimitive(false);// trueisPrimitive({});// falseisPrimitive([]);// falseCheck if the given value is an array.
isArray([1,2,3]);// trueisArray("hello world");// falseisArray(1);// falseisArray(newArray(1,2,3));// trueCheck if the value is a DOM element.
isElement(document.body);// trueisElement("hello world");// falseCheck whether the two values are equal. Uses the fast-deep-equal package. Works with all types.
isEqual(1,1);// trueisEqual(1,2);// falseisEqual("hello","hello");// trueisEqual(null,undefined);// falseisEqual({a: 1},{a: 1});// trueisEqual({a: 1},{a: 2});// falseisEqual([1,2,3],[1,2,3]);// trueCheck if the given value is empty. Works with strings, arrays, objects, and maps. Trims strings before checking.
isEmpty("");// trueisEmpty(" ");// trueisEmpty("hello world");// falseisEmpty(1);// falseisEmpty([]);// trueisEmpty([1,2,3]);// falseisEmpty({});// trueisEmpty({a: 1});// falseisEmpty(newMap());// trueisEmpty(newMap([["a",1]]));// falseCheck if the code is running in a browser environment.
isBrowser();// trueisBrowser();// falseCheck if the code is running in a Node.js environment.
isNode();// trueisNode();// falseUtility functions for working with numbers.
Produces a random number between min and max (inclusive). If only one argument is provided a number between 0 and the given number is returned. If floating is true, or either min or max are floats, a floating-point number is returned instead of an integer.
random(0,5);// 2random(5);// 2random(5,true);// 2.123876376random(0,5,true);// 2.123876376Parse a string into a number. If the string is empty or cannot be parsed, undefined is returned.
parseNumber("1");// 1parseNumber("1.5");// 1.5parseNumber("1.5.5");// undefinedparseNumber("");// undefinedUtility functions for working with objects. Both wrappers and custom functions.
Returns the value at path of object. If the resolved value is undefined, the defaultValue is returned in its place. Undefined will be returned if the path is not found or on failure. Wrapper around the "dot-prop" library.
constobj={a: {b: {c: "d"}}};getProperty(obj,"a.b.c");// => "d"getProperty(obj,"a.b");// => { c: "d" }getProperty({a: [{b: "c"}]},"a[0].b");// => "c"getProperty({a: [{b: "c"}]},"a[1].b");// => undefinedSets the value at path of object. If a portion of path doesn't exist, it's created. Arrays are created for missing index properties while objects are created for all other missing properties. Use deleteProperty to remove property values. Wrapper around the "dot-prop" library.
constobj={a: {b: {c: "d"}}};setProperty(obj,"a.b.c","hello");// => { a: { b: { c: "hello" }}}setProperty(obj,"a",hello);// => { a: "hello" }setProperty({},"a.b","hello");// => { a: { b: "hello" }}Checks if object has a property at path. If the resolved value is undefined, false is returned. Wrapper around the "dot-prop" library.
constobj={a: {b: {c: "d"}}};hasProperty(obj,"a.b.c");// => truehasProperty(obj,"a.b");// => truehasProperty(obj,"a.b.c.d");// => falseDeletes the property at path of object. Wrapper around the "dot-prop" library.
constobj={a: {b: {c: "d"}}};deleteProperty(obj,"a.b.c");// => truedeleteProperty(obj,"a.b");// => truedeleteProperty(obj,"a.b.c.d");// => falseStrictly typed version of Object.keys. Returns an array of keys of the object.
constobj={a: 1,b: 2,c: 3};objectKeys(obj);// => ["a", "b", "c"]objectKeys({});// => []Strictly typed version of Object.values. Returns an array of values of the object.
constobj={a: 1,b: 2,c: 3};objectValues(obj);// => [1, 2, 3]objectValues({});// => []Strictly typed version of Object.entries. Returns an array of key-value pairs of the object.
constobj={a: 1,b: 2,c: 3};objectEntries(obj);// => [["a", 1], ["b", 2], ["c", 3]]objectEntries({});// => []Deeply merges two or more objects. The last object in the arguments list overwrites previous values. No mutation. Arrays are overwritten. Uses the
deepmergelibrary.
constobj1={a: 1};constobj2={a: 2};merge(obj1,obj2);// => { a: 2 }constobj1={a: {b: 1}};constobj2={a: {c: 2}};merge(obj1,obj2);// => { a: { b: 1, c: 2 }}constobj1={a: {b: 1}};constobj2={a: {b: 2}};constobj3={a: {b: 3}};merge(obj1,obj2,obj3);// => { a: { b: 3 }}Deeply clones an object. No mutation.
constobj={a: {b: 1}};constcloned=clone(obj);cloned.a.b=2;console.log(obj.a.b);// => 1Used for setting default values. Deeply merges two objects. No mutation. The first object is the partial one, and the second object is the default one. If a value is already set in the partial object, it will not be overwritten.
constobj1={a: 1};constobj2={a: 2};defaults(obj1,obj2);// => { a: 1 }defaults(obj2,obj1);// => { a: 2 }Flips the keys and values of an object. If the object has duplicate values, the last key will be used.
constobj={a: 1,b: 2,c: 3};flip(obj);// => { 1: "a", 2: "b", 3: "c" }A result type that can be used to return a value or an error.
Returns true if the result is Ok. Narrows the type so you can safely access
.data.
constresult=Result.ok(42);if(result.isOk()){console.log(result.data);// 42}Returns true if the result is Err. Narrows the type so you can safely access
.error.
constresult=Result.err("not found");if(result.isErr()){console.log(result.error);// "not found"}If Ok, maps the value using the provided function and returns a new Ok result. If Err, does nothing and returns the original Err.
constdouble=(x: number)=>x*2;constaddOne=(x: number)=>x+1;Result.ok(5).map(double)// Ok(10).map(addOne);// Ok(11)Result.err("fail").map(double);// Err("fail") — untouchedIf Err, maps the error using the provided function and returns a new Err result. If Ok, does nothing and returns the original Ok.
consttoError=(msg: string)=>newError(msg);Result.err("not found").mapErr(toError);// Err(Error("not found"))Result.ok(42).mapErr(toError);// Ok(42) — untouchedIf Ok, runs a side-effect on the value without changing the result. Useful for logging or debugging. If Err, does nothing and returns the original Err.
constlog=(val: string)=>console.log("got:",val);constupper=(s: string)=>s.toUpperCase();Result.ok("hello").tap(log)// logs "got: hello", still Ok("hello").map(upper);// Ok("HELLO")If Err, runs a side-effect on the error without changing the result. Useful for logging errors. If Ok, does nothing and returns the original Ok.
constlogError=(e: string)=>console.error("failed:",e);constprefix=(e: string)=>`Request ${e}`;Result.err("timeout").tapErr(logError)// logs "failed: timeout", still Err("timeout").mapErr(prefix);// Err("Request timeout")If Ok, calls the provided function with the value and returns its Result. Useful for chaining operations that themselves can fail. If Err, does nothing and returns the original Err.
constparse=(s: string)=>Result.fromThrowable(JSON.parse)(s);constgetAge=(obj: any)=>(obj.age ? Result.ok(obj.age) : Result.err("missing age"));constvalidate=(age: number)=>(age>=18 ? Result.ok(age) : Result.err("too young"));Result.ok('{"age": 25}').andThen(parse)// Ok({ age: 25 }).andThen(getAge)// Ok(25).andThen(validate);// Ok(25)Pattern-matches on Ok/Err, calling the corresponding handler and returning its value.
constresult=Result.ok(42);constmessage=result.match({Ok: x=>`Success: ${x}`,Err: e=>`Failed: ${e}`,});// "Success: 42"Returns the Ok value. Throws an error if the result is Err. Use only when you are certain the result is Ok.
constresult=Result.ok(42);result.unwrap();// 42consterr=Result.err("fail");err.unwrap();// throws ErrorReturns the Ok value, or the provided default value if Err.
constok=Result.ok(42);ok.unwrapOr(0);// 42consterr=Result.err("fail");err.unwrapOr(0);// 0If Ok, asynchronously maps the value using the provided function and returns a new Ok result. If Err, does nothing and returns the original Err.
constfetchUser=async(id: number)=>{constres=awaitfetch(`/api/users/${id}`);returnres.json();};constuser=awaitResult.ok(1).mapAsync(fetchUser);// Ok({ name: "Alice", ... })If Err, asynchronously maps the error using the provided function and returns a new Err result. If Ok, does nothing and returns the original Ok.
constenrichError=async(code: string)=>{constmessage=awaitlookupErrorMessage(code);returnnewAppError(code,message);};constresult=awaitResult.err("not_found").mapErrAsync(enrichError);// Err(AppError("not_found", "Resource not found"))If Ok, asynchronously runs a side-effect on the value. Returns the original result unchanged. If Err, does nothing and returns the original Err.
consttrackEvent=async(user: User)=>{awaitanalytics.track("user_loaded",{id: user.id});};constresult=awaitResult.ok(user).tapAsync(trackEvent);// Ok(user) — unchangedIf Err, asynchronously runs a side-effect on the error. Returns the original result unchanged. If Ok, does nothing and returns the original Ok.
constreportError=async(e: string)=>{awaiterrorReporter.report(e);};constresult=awaitResult.err("timeout").tapErrAsync(reportError);// Err("timeout") — unchangedIf Ok, asynchronously calls the provided function and returns its Result. Useful for chaining async operations that themselves can fail. If Err, does nothing and returns the original Err.
constfetchOrders=async(userId: string)=>{constres=awaitfetch(`/api/orders/${userId}`);if(!res.ok)returnResult.err("fetch failed");returnResult.ok(awaitres.json());};constorders=awaitResult.ok("user-123").andThenAsync(fetchOrders);// Ok([...orders]) or Err("fetch failed")Runs a synchronous operation and converts thrown errors into Err. Use this for sync API/service work that can throw, such as parsing headers, URLs, or request data.
consttenantResult=Result.try(()=>newURL(request.url).pathname.split("/")[2],cause=>newApiError("Invalid tenant route",{ cause }));if(!tenantResult.ok)returntenantResult;Creates an Ok result.
constresult=Result.ok(42);Creates an Err result.
constresult=Result.err("Something went wrong");Returns true when a value has the Result shape. Useful at API boundaries where values are unknown, for example when a generic handler accepts either a raw response or a service Result.
constvalue: unknown=awaitmaybeReturnsResult();if(Result.isResult(value)){returnvalue.match({Ok: data=>({status: 200,body: data}),Err: error=>({status: 500,body: {message: String(error)}}),});}Runs an async operation and converts rejected promises or thrown errors into Err. This is useful for API service calls such as database queries, external SDK calls, or fetches.
constordersResult=awaitResult.tryAsync(()=>db.orders.findMany({ tenantId }),cause=>newApiError("DB error listing orders",{ cause }));if(!ordersResult.ok)returnordersResult;returnResult.ok(ordersResult.data.map(OrderListItem.fromDb));Converts a nullable value into a Result. Useful after lookups such as Array.find, Map.get, or database methods returning undefined.
constorderResult=Result.fromNullable(awaitdb.orders.findFirst({id: orderId, tenantId }),()=>newApiError("Order not found"));if(!orderResult.ok)returnorderResult;Combines multiple Results into one Result. Returns Ok with all successful values, or the first Err encountered. Useful for independent service validation steps before running a mutation.
constvalidation=Result.all([requirePositiveInteger(orderId,"Order ID"),requireNonEmpty(cancelReason,"Cancel reason"),requireTenantAccess(user,tenantId),]asconst);if(!validation.ok)returnvalidation;Wraps a potentially-throwing function and returns a ResultType. If the function throws, returns Err; otherwise, returns Ok.
constsafeParse=Result.fromThrowable(JSON.parse);constresult=safeParse('{"a":1}');if(result.ok){console.log(result.data);// parsed object}else{console.log(result.error);// error object}Wraps a potentially-throwing async function and returns a Promise of ResultType. If the function throws or rejects, returns Err; otherwise, returns Ok.
constsafeFetch=Result.fromAsyncThrowable(fetch);constresult=awaitsafeFetch("https://example.com");if(result.ok){console.log(result.data);// fetch response}else{console.log(result.error);// error object}Creates a Result factory locked to a specific error type. Useful when you want to own a Result type in your module with a consistent error shape.
classAppErrorextendsError{constructor(publiccode: number,message: string){super(message);}}constResult=createResult<AppError>();typeResult<T>=ResultType<T,AppError>;// Services return ResultsfunctiongetUser(id: string): Result<User>{constuser=db.find(id);if(!user)returnResult.err(newAppError(404,"User not found"));returnResult.ok(user);}functiongetUserOrders(user: User): Result<Order[]>{constorders=db.ordersFor(user.id);if(!orders)returnResult.err(newAppError(500,"DB failure"));returnResult.ok(orders);}// Chain with andThen + map, then match in the controllerconstresult=getUser(id).andThen(user=>getUserOrders(user)).map(orders=>orders.reduce((sum,o)=>sum+o.total,0));returnresult.match({Ok: total=>({status: 200,body: { total }}),Err: err=>({status: err.code,body: {message: err.message}}),});A simple result type that can be used to return a value or an error.
A simple result type that can be used to return a value or an error.
constresult=SimpleResult.ok(1);// or SimpleResult.errorif(result.ok){console.log(result.data);}else{console.log(result.message);}consterror=SimpleResult.error("error message");console.log(error.message);Create a wrapper around the simple result type. Making it possible to import the SimpleResult type from your own module. Without any custom error data and types. Use
createResultWithErrorDatafor custom error data and types.
constOwnResult=createSimpleResult();constresult=OwnResult.ok(1);// or OwnResult.errorif(result.ok){console.log(result.data);}else{console.log(result.message);}Create a custom Result type with error data and types.
typeMyErrorDataMap={network: {endpoint: string;statusCode: number};internal: {errorId: string;details: string};};typeDefaultError="UnknownError";constOwnResult=createResultWithErrorData<MyErrorDataMap,DefaultError>();consterror=OwnResult.error("error message",{type: "network",data: {endpoint: "http://example.com",statusCode: 404},});if(error.type==="network"){console.log(error.data.endpoint);}consterror=OwnResult.error("error message");console.log(error.type);// type "UnknownError"Create a custom Result type with error types, no data.
typeMyErrorType="NetworkError"|"InternalError";constOwnResult=createResultWithType<MyErrorType>();consterror=OwnResult.error("error message","NetworkError");if(error.type==="NetworkError"){console.log(error.message);}Create a custom Result type based on try expressions, with a Go-like syntax. Used to return a value or an error. Return value is a
TryExpressionResulttuple with an error and a value.
constResult=createTryExpressionResult();constgetResult=()=>{if(something()){returnResult.ok(1);}else{returnResult.error(newError("error"));}};const[error,value]=getResult();if(error){console.log(error.message);// Error is defined}else{console.log(value);// Value is defined}Utilities for working with strings.
Capitalizes the first letter of a given string and converts the rest of the letters to lowercase.
capitalize("hello");// returns 'Hello'capitalize("HELLO");// returns 'Hello'Generate a random string with the length provided, defaults to 16.
randomString();// returns 'Fwf4552Dd2'randomString(5);// return 'f5l32'Check if a string matches a wildcard pattern. Uses the "wildcard-match" library.
wildcardMatch("/foo/bar","/foo/*");// returns truewildcardMatch("/foo/bar","/foo/bar");// returns truewildcardMatch("/foo/bar","/foo/bar/*");// returns falseEnsure a string starts with a given prefix.
ensurePrefix("hello","foo");// returns 'foohello'ensurePrefix("foohello","foo");// returns 'foohello'ensurePrefix("hello","hello");// returns 'hello'Ensure a string ends with a given suffix.
ensureSuffix("hello","foo");// returns 'hellofoo'ensureSuffix("hellofoo","foo");// returns 'hellofoo'ensureSuffix("hello","hello");// returns 'hello'Simple templating function that replaces {0}, {1} or {{key}} with the provided arguments.
template("hello {0}","world");// returns 'hello world'template("hello {0} {1}","world","foo");// returns 'hello world foo'template("hello {0} {1}","world");// returns 'hello world {1}'template("hello {{name}}",{name: "world"});// returns 'hello world'template("hello {{name}}, I am {{me}}",{name: "world",me: "Kent"});// returns 'hello world, I am Kent'template("hello {{name}}",{name: "world",foo: "bar"});// returns 'hello world'template("hello {{name}}",{foo: "bar"});// returns 'hello {{name}}'Escape HTML special characters.
escapeHtml("<div>hello</div>");// returns '<div>hello</div>'Unescape HTML special characters. Opposite of escapeHtml.
unescapeHtml("<div>hello</div>");// returns '<div>hello</div>'Escape RegExp special characters.
escapeRegExp("hello world");// returns 'hello world'escapeRegExp("hello*world");// returns 'hello\\*world'escapeRegExp("hello?world");// returns 'hello\\?world'escapeRegExp("hello(world");// returns 'hello\\(world'Slugify a string. Converts a string to lowercase, removes non-word characters and replaces spaces with dashes.
slugify("hello world");// returns 'hello-world'slugify("hello world!");// returns 'hello-world'slugify("");// returns ''slugify("This is a long sentence that should be slugified!!");// returns 'this-is-a-long-sentence-that-should-be-slugified'Truncate a string to a given length. Adds an ellipsis to the end of the string if it was truncated.
truncate("hello world",5);// returns 'hello...'truncate("hello world",5,"...more");// returns 'hello...more'truncate("hello world",100);// returns 'hello world'truncate("hello world",5,"");// returns 'hello'truncate("hello world",5,"...");// returns 'hello...'Converts a string to camelCase format (using scule library).
toCamelCase("hello-world");// returns 'helloWorld'toCamelCase("hello_world");// returns 'helloWorld'toCamelCase("HelloWorld");// returns 'helloWorld'Converts a string to snake_case format (using scule library).
toSnakeCase("helloWorld");// returns 'hello_world'toSnakeCase("hello-world");// returns 'hello_world'toSnakeCase("HelloWorld");// returns 'hello_world'Converts a string to Title Case format (using scule library).
toTitleCase("helloWorld");// returns 'Hello World'toTitleCase("hello-world");// returns 'Hello World'toTitleCase("hello_world");// returns 'Hello World'Converts a string to Train-Case format (using scule library).
toTrainCase("helloWorld");// returns 'Hello-World'toTrainCase("hello_world");// returns 'Hello-World'toTrainCase("HelloWorld");// returns 'Hello-World'Converts a string to kebab-case format (using scule library).
toKebabCase("helloWorld");// returns 'hello-world'toKebabCase("hello_world");// returns 'hello-world'toKebabCase("HelloWorld");// returns 'hello-world'Converts a string to flat case format (no separators, all lowercase) (using scule library).
toFlatCase("helloWorld");// returns 'helloworld'toFlatCase("hello-world");// returns 'helloworld'toFlatCase("Hello_World");// returns 'helloworld'Simple utility function for tests
Attempt to run a synchronous function, and return a fallback value if it throws an error. Defaults to undefined if nothing is provided.
constresult=attempt(()=>1);// 1constresult=attempt(()=>{thrownewError("test");});// undefinedconstresult=attempt(()=>{thrownewError("test");},{fallbackValue: 1});// 1Attempt to run an asynchronous function, and return a fallback value if it throws an error. Defaults to undefined if nothing is provided.
constresult=awaitattempt(async()=>1);// 1constresult=awaitattempt(async()=>{thrownewError("test");});// undefinedconstresult=awaitattempt(async()=>{thrownewError("test");},{fallbackValue: 1});// 1Attempt to run an async function like in Go, returning a tuple with the error and the result.
const[error,result]=awaitto(async()=>1);// [undefined, 1]const[error,result]=awaitto(async()=>{thrownewError("test");});// [Error("test"), undefined]Attempt to run an sync function like in Go, returning a tuple with the error and the result.
const[error,result]=to(()=>1);// [undefined, 1]const[error,result]=to(()=>{thrownewError("test");});// [Error("test"), undefined]Create a new create mock function to update the base mock with the partial mock. Will overwrite arrays instead of merging them.
constnumbersMock={a: 1,b: 2,c: 3};constupdatedData={a: 2};exportconstcreateNumbersMock=createMockCreator(numbersMock);createNumbersMock(updatedData);// => { a: 2, b: 2, c: 3 }