A collection of general-purpose TypeScript utilities for common programming tasks. This library provides type-safe, well-tested utility functions organized into logical categories.
npm install swiss-army-utilsImport utilities directly from their category paths:
import { isDefined } from 'swiss-army-utils/filter/isDefined';
import { asyncMap } from 'swiss-army-utils/map-reduce/asyncMap';
import { sleep } from 'swiss-army-utils/functions/sleep';- BaseError ⇐
Error Base error class that all custom errors in this library extend from. Provides a flag to identify errors from this library.
- InvalidInputError ⇐
BaseError Error class for invalid input errors. Extends BaseError to provide a specific error type for input validation failures.
- TimeoutError ⇐
Error Error class for timeout operations. Automatically generates a detailed message with timing information.
- raise ⇒
never Throws an error immediately. Useful for inline error throwing in expressions. Accepts either an Error object or a string message.
- booleanAsStringSchema :
z.ZodSchema.<boolean> Zod schema that parses boolean values from string representations. Accepts 'true' or 'false' strings and transforms them to actual boolean values.
- nonEmptyStringSchema :
z.ZodSchema.<string> Zod schema that validates strings are not empty (have at least 1 character). Useful for required string fields in forms and APIs.
- numberAsStringSchema :
z.ZodSchema.<number> Zod schema that parses number values from string representations. Uses stringToNumber for validation and transformation.
- isDeepEqual(a, b) ⇒
boolean|void Performs a deep equality comparison between two values. Handles arrays, objects, dates, regular expressions, and primitive values. Type-safe: only returns boolean when types match, otherwise returns void.
- createDependencyContainer(options) ⇒
DependencyContainer.<SyncDependencies, AsyncDependencies> Creates a dependency injection container for managing application dependencies. Supports both synchronous and asynchronous dependencies with lazy initialization. Containers can be extended to add new dependencies while maintaining type safety.
- getErrorMessage(error) ⇒
string Extracts an error message from an unknown error value. Handles Error objects, strings, objects, and other types gracefully.
- filterUnique(items, getKey) ⇒
Array.<T> Filters an array to keep only unique items based on a key extraction function. When duplicate keys are found, the last occurrence is kept.
- isDefined(value) ⇒
boolean Type guard that checks if a value is neither undefined nor null. This is useful for filtering arrays and narrowing types in TypeScript.
- findOrThrow(arr, predicate) ⇒
T Finds the first item in the array that matches the predicate, throwing an error if no match is found.
- firstOrThrow(items) ⇒
T Returns the first item in the array, throwing an error if the array is empty.
- indexOrThrow(items, index) ⇒
T Returns the item at the specified index in the array, throwing an error if the index is out of bounds.
- makeThrottled(options, fn) ⇒
function Creates a throttled version of a function that enforces a minimum delay between executions. Multiple calls made during the delay period will share the same promise and return the same result. After the delay period, subsequent calls will trigger a new execution.
- sleep(ms) ⇒
Promise.<void> Asynchronously pauses execution for a specified duration. Returns a promise that resolves after the given number of milliseconds.
- asTuple(arr) ⇒
T Type-level function that ensures the input array is treated as a tuple type. This is useful for preserving exact array literal types.
- asyncFlatMap(array, mapper) ⇒
Promise.<Array> Asynchronously maps over an array or async iterable and flattens the results. Equivalent to calling asyncMap followed by Array.flat(). The mapping is performed sequentially to maintain order.
- asyncMap(iterator, mapper) ⇒
Promise.<Array.<R>> Asynchronously maps over an array or async iterable, applying an async mapper function to each item. The mapping is performed sequentially (not in parallel) to maintain order and avoid overwhelming resources.
- asyncReduce(items, reducer, initialResult) ⇒
Promise.<Result> Asynchronously reduces an array to a single value using an async reducer function. The reduction is performed sequentially, processing one item at a time.
- batchArray(array, batchSize) ⇒
Array.<Array.<T>> Splits an array into smaller arrays (batches) of a specified size. Each batch will contain at most
batchSizeitems.- batchArrayByWeights(items, batchSize, getWeight) ⇒
Array.<Array.<T>> Splits an array into smaller arrays (batches) based on weighted sizes. Items are grouped into batches where the total weight doesn't exceed the specified batch size.
- batchAsyncIterableByWeights(items, batchSize, getWeight)
Asynchronously splits an async iterable into batches based on weighted sizes. Items are grouped into batches where the total weight doesn't exceed the specified batch size. This is an async generator that yields batches as they are formed.
- groupBy(array, getKey, initialValue) ⇒
Record.<Key, Array.<T>> Groups the elements of an array based on a key derived from each element.
- pluckIds(items, idGetter) ⇒
Array Extracts unique IDs from an array of objects using an ID getter function. The function flattens nested arrays up to 10 levels deep, filters out null/undefined values, and returns a deduplicated array of IDs.
- roundToDecimals(value, decimals) ⇒
number - stringToNumber(value) ⇒
number Safely converts a string to a number with validation. Throws an error if the string cannot be converted to a valid finite number.
- toSorted(array, getKey, order) ⇒
Array.<T> Sorts an array by a key extracted from each item, returning a new sorted array. The original array is not modified.
- createRange(length) ⇒
Array.<number> Creates an array of consecutive integers from 0 to length-1.
- createSingletonAsync(options) ⇒
function Creates an async singleton that lazily fetches and caches a value. The cached value is validated before each use and refreshed if invalid. Handles concurrent calls by ensuring only one fetch happens at a time.
- createSingletonSync(options) ⇒
function Creates a synchronous singleton that lazily fetches and caches a value. The cached value is validated before each use and refreshed if invalid.
- callInOrderWithErrorHandling(handlers, params)
Calls all handlers in order, collecting errors and throwing them at the end. If only one error occurs, throws that error directly. If multiple errors occur, throws an AggregateError.
- createSubject() ⇒
Object Creates a subject (observable) for event-driven programming. Allows subscribers to listen for events and emit events to all subscribers. Handlers are called in order, and all handlers are executed even if some fail.
- mergeSubjects(subjects) ⇒
Object Merges multiple subjects into a single subscribable subject. A handler subscribed to the merged subject will receive events from all source subjects. Note: The merged subject cannot emit events, only subscribe to them.
- filterObjectFields(object, filter) ⇒
Record.<string, Value> Creates a new object containing only the entries that pass the filter function. The filter function receives both the value and key for each entry.
- mapObjectFields(obj, mapFn) ⇒
Record.<string, TResult> Transforms an object by mapping over its key-value pairs. The mapping function receives each key-value pair as a tuple and returns a new tuple.
- omit(obj, ...keys) ⇒
Object Creates a new object by excluding specified keys from an existing object. Returns a copy of the object without the omitted properties.
- pick(obj, keys) ⇒
Object Creates a new object by picking specified keys from an existing object. Only includes properties that exist in the source object.
Base error class that all custom errors in this library extend from. Provides a flag to identify errors from this library.
Kind: global class
Extends: Error
Example
class CustomError extends BaseError {}
const err = new CustomError('Something went wrong');
if (err.isBaseError) {
// Handle custom error
}InvalidInputError ⇐ BaseError
Error class for invalid input errors. Extends BaseError to provide a specific error type for input validation failures.
Kind: global class
Extends: BaseError
Example
throw new InvalidInputError('User ID must be a positive number');Throws an error immediately. Useful for inline error throwing in expressions. Accepts either an Error object or a string message.
Kind: global constant
Returns: never - Never returns (always throws).
Throws:
ErrorAlways throws the provided error or creates a new Error from the string.
| Param | Type | Description |
|---|---|---|
| error | Error | string |
The error to throw, either an Error object or string message. |
Example
const value = someCondition ? validValue : raise('Invalid condition');
const result = data ?? raise(new Error('Data is required'));Zod schema that parses boolean values from string representations. Accepts 'true' or 'false' strings and transforms them to actual boolean values.
Kind: global constant
Example
booleanAsStringSchema.parse('true'); // returns true
booleanAsStringSchema.parse('false'); // returns false
booleanAsStringSchema.parse('yes'); // throws ZodErrorZod schema that validates strings are not empty (have at least 1 character). Useful for required string fields in forms and APIs.
Kind: global constant
Example
nonEmptyStringSchema.parse('hello'); // returns 'hello'
nonEmptyStringSchema.parse(''); // throws ZodError with 'This field cannot be empty'Zod schema that parses number values from string representations. Uses stringToNumber for validation and transformation.
Kind: global constant
Example
numberAsStringSchema.parse('123'); // returns 123
numberAsStringSchema.parse('3.14'); // returns 3.14
numberAsStringSchema.parse('abc'); // throws ZodErrorPerforms a deep equality comparison between two values. Handles arrays, objects, dates, regular expressions, and primitive values. Type-safe: only returns boolean when types match, otherwise returns void.
Kind: global function
Returns: boolean | void - True if values are deeply equal, false otherwise. Returns void if types don't match.
| Param | Type | Description |
|---|---|---|
| a | T |
The first value to compare. |
| b | U |
The second value to compare. |
Example
isDeepEqual({ a: 1, b: { c: 2 } }, { a: 1, b: { c: 2 } }); // returns true
isDeepEqual([1, 2, 3], [1, 2, 3]); // returns true
isDeepEqual(new Date('2024-01-01'), new Date('2024-01-01')); // returns true
isDeepEqual({ a: 1 }, { a: 2 }); // returns falseCreates a dependency injection container for managing application dependencies. Supports both synchronous and asynchronous dependencies with lazy initialization. Containers can be extended to add new dependencies while maintaining type safety.
Kind: global function
Returns: DependencyContainer.<SyncDependencies, AsyncDependencies> - A dependency container with extend and load capabilities.
| Param | Type | Description |
|---|---|---|
| options | Object |
Configuration for dependency creation. |
| options.createSyncDependencies | function |
Optional function that creates synchronous dependencies. |
| options.createAsyncDependencies | function |
Optional function that creates asynchronous dependencies. |
Example
const container = createDependencyContainer({
createSyncDependencies: () => ({
config: { apiUrl: 'https://api.example.com' }
}),
createAsyncDependencies: async () => ({
db: await connectToDatabase()
})
});
const syncDeps = container.getSyncDependencies();
const allDeps = await container.loadAllDependencies();
const extended = container.extend({
createSyncDependencies: (parent) => ({
logger: createLogger(parent.getSyncDependencies().config)
})
});Extracts an error message from an unknown error value. Handles Error objects, strings, objects, and other types gracefully.
Kind: global function
Returns: string - A string representation of the error message.
| Param | Type | Description |
|---|---|---|
| error | unknown |
The error value to extract a message from. |
Example
getErrorMessage(new Error('Something went wrong')); // returns 'Something went wrong'
getErrorMessage('Error string'); // returns 'Error string'
getErrorMessage({ code: 404 }); // returns '{"code":404}'
getErrorMessage(null); // returns 'An unknown error occurred'Filters an array to keep only unique items based on a key extraction function. When duplicate keys are found, the last occurrence is kept.
Kind: global function
Returns: Array.<T> - An array containing only unique items based on the extracted keys.
| Param | Type | Description |
|---|---|---|
| items | Array.<T> |
The array of items to filter. |
| getKey | function |
Function that extracts a unique key from each item. |
Example
const items = [
{ id: '1', name: 'a' },
{ id: '2', name: 'b' },
{ id: '1', name: 'c' }
];
filterUnique(items, (item) => item.id);
// returns [{ id: '1', name: 'c' }, { id: '2', name: 'b' }]Type guard that checks if a value is neither undefined nor null. This is useful for filtering arrays and narrowing types in TypeScript.
Kind: global function
Returns: boolean - True if the value is not undefined and not null, false otherwise.
| Param | Type | Description |
|---|---|---|
| value | T | undefined | null |
The value to check for being defined. |
Example
const values = [1, null, 2, undefined, 3];
const definedValues = values.filter(isDefined);
// returns [1, 2, 3]
const maybeValue: string | null | undefined = getOptionalValue();
if (isDefined(maybeValue)) {
// TypeScript knows maybeValue is string here
console.log(maybeValue.toUpperCase());
}Finds the first item in the array that matches the predicate, throwing an error if no match is found.
Kind: global function
Returns: T - The first item that satisfies the predicate.
Throws:
ErrorIf no item matches the predicate.
| Param | Type | Description |
|---|---|---|
| arr | Array.<T> |
The array to search. |
| predicate | function |
Function to test each item. Returns true for the item to be returned. |
Example
const numbers = [1, 2, 3, 4];
findOrThrow(numbers, n => n === 2); // returns 2
findOrThrow(numbers, n => n > 2); // returns 3
findOrThrow(numbers, n => n === 5); // throws Error: Item not foundReturns the first item in the array, throwing an error if the array is empty.
Kind: global function
Returns: T - The first item in the array.
Throws:
ErrorIf the array is empty.
| Param | Type | Description |
|---|---|---|
| items | Array.<T> |
The array to get the first item from. |
Example
const items = ['a', 'b', 'c'];
firstOrThrow(items); // returns 'a'
firstOrThrow([]); // throws Error: No item found at index 0Returns the item at the specified index in the array, throwing an error if the index is out of bounds.
Kind: global function
Returns: T - The item at the specified index.
Throws:
ErrorIf no item exists at the specified index.
| Param | Type | Description |
|---|---|---|
| items | Array.<T> |
The array to get the item from. |
| index | number |
The index of the item to retrieve. |
Example
const items = ['a', 'b', 'c'];
indexOrThrow(items, 1); // returns 'b'
indexOrThrow(items, 3); // throws Error: No item found at index 3
indexOrThrow(items, -1); // throws Error: No item found at index -1Creates a throttled version of a function that enforces a minimum delay between executions. Multiple calls made during the delay period will share the same promise and return the same result. After the delay period, subsequent calls will trigger a new execution.
Kind: global function
Returns: function - A throttled function that returns a promise. If multiple calls are made within the delay period,
they will all receive the same promise and result.
| Param | Type | Description |
|---|---|---|
| options | Object |
Configuration object. |
| options.minDelay | number |
Minimum delay in milliseconds between function executions. |
| fn | function |
The function to throttle. Can be synchronous or asynchronous. |
Example
// Throttle an API call to at most once per second
const fetchData = () => fetch('/api/data').then(r => r.json());
const throttledFetch = makeThrottled({ minDelay: 1000 }, fetchData);
// First call executes immediately
const result1 = await throttledFetch();
// Calls within 1 second share the same promise
const promise2 = throttledFetch();
const promise3 = throttledFetch();
// promise2 === promise3
// After 1 second delay, new call triggers another execution
await sleep(1100);
const result2 = await throttledFetch(); // New executionAsynchronously pauses execution for a specified duration. Returns a promise that resolves after the given number of milliseconds.
Kind: global function
Returns: Promise.<void> - A promise that resolves after the specified delay.
| Param | Type | Description |
|---|---|---|
| ms | number |
Duration in milliseconds to sleep. |
Example
// Sleep for 1 second
await sleep(1000);
// Use in a loop with delays
for (let i = 0; i < 5; i++) {
console.log(i);
await sleep(500);
}Type-level function that ensures the input array is treated as a tuple type. This is useful for preserving exact array literal types.
Kind: global function
Returns: T - The same array, but with tuple type preservation.
| Param | Type | Description |
|---|---|---|
| arr | T |
The array to treat as a tuple. |
Example
const tuple = asTuple([1, 2, 3]); // Type: [1, 2, 3]
const array = [1, 2, 3]; // Type: number[]Asynchronously maps over an array or async iterable and flattens the results. Equivalent to calling asyncMap followed by Array.flat(). The mapping is performed sequentially to maintain order.
Kind: global function
Returns: Promise.<Array> - A promise that resolves to a flattened array of mapped results.
| Param | Type | Description |
|---|---|---|
| array | Array.<T> | AsyncIterable.<T> |
The array or async iterable to map over. |
| mapper | function |
Async function that transforms each item. Receives the item and its index. |
Example
const words = ['hello', 'world'];
const letters = await asyncFlatMap(words, async (word, index) => {
await sleep(100); // Simulate async operation
return word.split('');
});
// returns ['h', 'e', 'l', 'l', 'o', 'w', 'o', 'r', 'l', 'd']
// Without asyncFlatMap, you'd need:
// const mapped = await asyncMap(words, mapper);
// const flattened = mapped.flat();Asynchronously maps over an array or async iterable, applying an async mapper function to each item. The mapping is performed sequentially (not in parallel) to maintain order and avoid overwhelming resources.
Kind: global function
Returns: Promise.<Array.<R>> - A promise that resolves to an array of mapped results.
| Param | Type | Description |
|---|---|---|
| iterator | Array.<T> | AsyncIterable.<T> |
The array or async iterable to map over. |
| mapper | function |
Async function that transforms each item. Receives the item and its index. |
Example
// With array
const numbers = [1, 2, 3];
const doubled = await asyncMap(numbers, async (n, index) => {
await sleep(100); // Simulate async operation
return n * 2;
});
// returns [2, 4, 6]
// With async iterable
async function* generateNumbers() {
yield 1; yield 2; yield 3;
}
const result = await asyncMap(generateNumbers(), async (n) => n * 2);
// returns [2, 4, 6]Asynchronously reduces an array to a single value using an async reducer function. The reduction is performed sequentially, processing one item at a time.
Kind: global function
Returns: Promise.<Result> - A promise that resolves to the final accumulated result.
| Param | Type | Description |
|---|---|---|
| items | Array.<Item> |
The array to reduce. |
| reducer | function |
Async function that combines the accumulator with each item. |
| initialResult | Result |
The initial value for the accumulator. |
Example
const numbers = [1, 2, 3, 4];
const sum = await asyncReduce(
numbers,
async (total, num) => {
await sleep(100); // Simulate async operation
return total + num;
},
0
);
// returns 10
const words = ['hello', 'world'];
const combined = await asyncReduce(
words,
async (result, word) => result + ' ' + word,
''
);
// returns ' hello world'Splits an array into smaller arrays (batches) of a specified size.
Each batch will contain at most batchSize items.
Kind: global function
Returns: Array.<Array.<T>> - An array of arrays, where each sub-array is a batch.
| Param | Type | Description |
|---|---|---|
| array | Array.<T> |
The array to split into batches. |
| batchSize | number |
The maximum number of items per batch. |
Example
batchArray([1, 2, 3, 4, 5], 2);
// returns [[1, 2], [3, 4], [5]]
batchArray(['a', 'b', 'c'], 3);
// returns [['a', 'b', 'c']]Splits an array into smaller arrays (batches) based on weighted sizes. Items are grouped into batches where the total weight doesn't exceed the specified batch size.
Kind: global function
Returns: Array.<Array.<T>> - An array of arrays, where each sub-array is a batch with total weight ≤ batchSize.
| Param | Type | Description |
|---|---|---|
| items | Array.<T> |
The array to split into batches. |
| batchSize | number |
The maximum total weight allowed per batch. |
| getWeight | function |
Function to calculate the weight of each item. |
Example
const items = ['a', 'bb', 'ccc', 'dddd'];
batchArrayByWeights(items, 5, item => item.length);
// returns [['a', 'bb'], ['ccc'], ['dddd']]
// Batch 1: 'a' (1) + 'bb' (2) = 3 ≤ 5
// Batch 2: 'ccc' (3) = 3 ≤ 5
// Batch 3: 'dddd' (4) = 4 ≤ 5Asynchronously splits an async iterable into batches based on weighted sizes. Items are grouped into batches where the total weight doesn't exceed the specified batch size. This is an async generator that yields batches as they are formed.
Kind: global function
| Param | Type | Description |
|---|---|---|
| items | AsyncIterable.<T> |
The async iterable to split into batches. |
| batchSize | number |
The maximum total weight allowed per batch. |
| getWeight | function |
Function to calculate the weight of each item. |
Example
async function* generateItems() {
yield 'a'; yield 'bb'; yield 'ccc'; yield 'dddd';
}
for await (const batch of batchAsyncIterableByWeights(generateItems(), 5, item => item.length)) {
console.log(batch);
}
// Outputs: ['a', 'bb'], ['ccc'], ['dddd']Groups the elements of an array based on a key derived from each element.
Kind: global function
Returns: Record.<Key, Array.<T>> - An object where each key maps to an array of elements that share that key.
| Param | Type | Description |
|---|---|---|
| array | Array.<T> |
The array to be grouped. |
| getKey | function |
A function that derives the key from each element. |
| initialValue | Record.<Key, Array.<T>> |
An initial value for the grouped result. |
Example
const data = [
{ category: 'fruit', name: 'apple' },
{ category: 'vegetable', name: 'carrot' },
{ category: 'fruit', name: 'banana' },
];
const grouped = groupBy(data, item => item.category, {});
// Result:
// {
// fruit: [
// { category: 'fruit', name: 'apple' },
// { category: 'fruit', name: 'banana' },
// ],
// vegetable: [
// { category: 'vegetable', name: 'carrot' },
// ],
// };Extracts unique IDs from an array of objects using an ID getter function. The function flattens nested arrays up to 10 levels deep, filters out null/undefined values, and returns a deduplicated array of IDs.
Kind: global function
Returns: Array - An array of unique, non-null IDs.
| Param | Type | Description |
|---|---|---|
| items | Array.<T> |
The array of objects to extract IDs from. |
| idGetter | function |
Function that extracts the ID(s) from each item. Can return single values or nested arrays. |
Example
const users = [
{ id: 1, friendIds: [2, 3] },
{ id: 2, friendIds: [1] },
{ id: 3, friendIds: [1, 2] }
];
// Extract user IDs
pluckIds(users, user => user.id);
// returns [1, 2, 3]
// Extract friend IDs (flattened and deduplicated)
pluckIds(users, user => user.friendIds);
// returns [2, 3, 1]
// Extract both user ID and friend IDs
pluckIds(users, user => [user.id, user.friendIds]);
// returns [1, 2, 3]Kind: global function
Returns: number - The rounded value.
| Param | Type | Description |
|---|---|---|
| value | number |
The value to round. |
| decimals | number |
The number of decimal places to round to. |
Example
roundToDecimals(3.14159, 2); // returns 3.14
roundToDecimals(3.14159, 0); // returns 3
roundToDecimals(3.14159, 3); // returns 3.142
roundToDecimals(3.14, 5); // returns 3.14Safely converts a string to a number with validation. Throws an error if the string cannot be converted to a valid finite number.
Kind: global function
Returns: number - The parsed number.
Throws:
ErrorWhen the string is empty, not a number, or represents an infinite value.
| Param | Type | Description |
|---|---|---|
| value | string |
The string to convert to a number. |
Example
stringToNumber('123'); // returns 123
stringToNumber('3.14'); // returns 3.14
stringToNumber('-42'); // returns -42
stringToNumber('abc'); // throws Error: Invalid number: abc
stringToNumber(''); // throws Error: Invalid number:
stringToNumber('Infinity'); // throws Error: Invalid number: InfinitySorts an array by a key extracted from each item, returning a new sorted array. The original array is not modified.
Kind: global function
Returns: Array.<T> - A new array with the same items sorted by the specified key and order.
| Param | Type | Description |
|---|---|---|
| array | Array.<T> |
The array to sort. |
| getKey | function |
Function to extract the sort key from each item. |
| order | string |
Sort order, either 'asc' for ascending or 'desc' for descending. Defaults to 'asc'. |
Example
const users = [{ name: 'John', age: 30 }, { name: 'Jane', age: 25 }];
// Sort by name ascending
toSorted(users, user => user.name);
// returns [{ name: 'Jane', age: 25 }, { name: 'John', age: 30 }]
// Sort by age descending
toSorted(users, user => user.age, 'desc');
// returns [{ name: 'John', age: 30 }, { name: 'Jane', age: 25 }]Creates an array of consecutive integers from 0 to length-1.
Kind: global function
Returns: Array.<number> - An array of integers from 0 to length-1.
Throws:
ErrorIf length is negative.
| Param | Type | Description |
|---|---|---|
| length | number |
The number of elements in the range. Must be non-negative. |
Example
createRange(5); // returns [0, 1, 2, 3, 4]
createRange(0); // returns []
createRange(-1); // throws ErrorCreates an async singleton that lazily fetches and caches a value. The cached value is validated before each use and refreshed if invalid. Handles concurrent calls by ensuring only one fetch happens at a time.
Kind: global function
Returns: function - A function that returns the singleton value, fetching it if necessary.
Throws:
ErrorIf the freshly fetched value is invalid.
| Param | Type | Description |
|---|---|---|
| options | Object |
Configuration object. |
| options.getValue | function |
Function that fetches the value asynchronously. |
| options.isValid | function |
Function that checks if the cached value is still valid. |
Example
const getToken = createSingleton({
getValue: async () => fetchAuthToken(),
isValid: (token) => !token.isExpired
});
// First call fetches the token
const token1 = await getToken();
// Subsequent calls return cached token if valid
const token2 = await getToken(); // Same token if still valid
// Concurrent calls share the same fetch
const [token3, token4] = await Promise.all([getToken(), getToken()]);Creates a synchronous singleton that lazily fetches and caches a value. The cached value is validated before each use and refreshed if invalid.
Kind: global function
Returns: function - A function that returns the singleton value, fetching it if necessary.
Throws:
ErrorIf the freshly fetched value is invalid.
| Param | Type | Description |
|---|---|---|
| options | Object |
Configuration object. |
| options.getValue | function |
Function that fetches the value synchronously. |
| options.isValid | function |
Function that checks if the cached value is still valid. |
Example
const getConfig = createSingletonSync({
getValue: () => loadConfigFromFile(),
isValid: (config) => config.version === expectedVersion
});
// First call fetches the config
const config1 = getConfig();
// Subsequent calls return cached config if valid
const config2 = getConfig(); // Same config if still validCalls all handlers in order, collecting errors and throwing them at the end. If only one error occurs, throws that error directly. If multiple errors occur, throws an AggregateError.
Kind: global function
Throws:
ErrorThe single error if only one handler fails.AggregateErrorIf multiple handlers fail.
| Param | Type | Description |
|---|---|---|
| handlers | Set.<Handler.<TParams>> |
Set of handler functions to call. |
| params | TParams |
Parameters to pass to each handler. |
Creates a subject (observable) for event-driven programming. Allows subscribers to listen for events and emit events to all subscribers. Handlers are called in order, and all handlers are executed even if some fail.
Kind: global function
Returns: Object - An object with subscribe and emit methods.
Example
const subject = createSubject<string>();
// Subscribe to events
const unsubscribe = subject.subscribe(async (message) => {
console.log('Received:', message);
});
// Emit events to all subscribers
await subject.emit('Hello, world!');
// Unsubscribe when done
unsubscribe();Merges multiple subjects into a single subscribable subject. A handler subscribed to the merged subject will receive events from all source subjects. Note: The merged subject cannot emit events, only subscribe to them.
Kind: global function
Returns: Object - A merged subject with only a subscribe method (no emit).
| Param | Type | Description |
|---|---|---|
| subjects | Array.<Subject.<THandlerParams>> |
Array of subjects to merge. |
Example
const subject1 = createSubject<string>();
const subject2 = createSubject<string>();
const merged = mergeSubjects([subject1, subject2]);
// Subscribe once to receive events from both subjects
merged.subscribe((message) => {
console.log('Received from any subject:', message);
});
await subject1.emit('From subject1');
await subject2.emit('From subject2');
// Both messages are received by the merged subscriberCreates a new object containing only the entries that pass the filter function. The filter function receives both the value and key for each entry.
Kind: global function
Returns: Record.<string, Value> - A new object with only the filtered entries.
| Param | Type | Description |
|---|---|---|
| object | Record.<string, Value> |
The object to filter. |
| filter | function |
Function that tests each value and key. Returns true to keep the entry. |
Example
const scores = { alice: 85, bob: 92, charlie: 78, diana: 95 };
const highScores = filterObjectFields(scores, (score) => score >= 90);
// returns { bob: 92, diana: 95 }
const startsWithD = filterObjectFields(scores, (_, key) => key.startsWith('d'));
// returns { diana: 95 }Transforms an object by mapping over its key-value pairs. The mapping function receives each key-value pair as a tuple and returns a new tuple.
Kind: global function
Returns: Record.<string, TResult> - A new object with transformed entries.
| Param | Type | Description |
|---|---|---|
| obj | Record.<string, TMapped> |
The object to transform. |
| mapFn | function |
Function that maps each [key, value] tuple to a new [key, value] tuple. |
Example
const prices = { apple: 1, banana: 2, orange: 3 };
const doubled = mapObjectFields(prices, ([key, value]) => [key, value * 2]);
// returns { apple: 2, banana: 4, orange: 6 }
const prefixed = mapObjectFields(prices, ([key, value]) => [`fruit_${key}`, value]);
// returns { fruit_apple: 1, fruit_banana: 2, fruit_orange: 3 }Creates a new object by excluding specified keys from an existing object. Returns a copy of the object without the omitted properties.
Kind: global function
Returns: Object - A new object without the specified keys.
| Param | Type | Description |
|---|---|---|
| obj | Object |
The source object to omit from. |
| ...keys | string |
Keys to omit from the object. Can be provided as separate arguments or arrays. |
Example
const user = { id: 1, name: 'John', email: 'john@example.com', password: 'secret' };
const publicUser = omit(user, 'password');
// returns { id: 1, name: 'John', email: 'john@example.com' }
const minimal = omit(user, 'password', 'email');
// returns { id: 1, name: 'John' }Creates a new object by picking specified keys from an existing object. Only includes properties that exist in the source object.
Kind: global function
Returns: Object - A new object containing only the specified keys.
| Param | Type | Description |
|---|---|---|
| obj | Object |
The source object to pick from. |
| keys | Array |
Array of keys to pick from the object. |
Example
const user = { id: 1, name: 'John', email: 'john@example.com', age: 30 };
const userSummary = pick(user, ['id', 'name']);
// returns { id: 1, name: 'John' }npm test- Run all testsnpm run lint- Lint the source codenpm run build- Build the librarynpm run format- Format code with Prettiernpm run updateReadme- Generate README documentation from JSDoc commentsnpm run checks- Check format, run lint, tests and buildnpm run dev- Format files, lint, test, build and regenerate README file
- Run
npm run new-version [patch | minor | major] - Run
npm publish --dry-runand verify output - Run
npm publish
This repository follows these core principles:
- Functional programming - Pure functions without side effects
- Immutability - Data is never mutated
- Composition - Small, composable utilities
- Modularity - Each utility is independent
- Single responsibility - Each function does one thing well
- Type safety - Full TypeScript support with strict typing
MIT