Skip to content

Repository files navigation

swiss-army-utils

A collection of general-purpose TypeScript utilities for common programming tasks. This library provides type-safe, well-tested utility functions organized into logical categories.

Installation

npm install swiss-army-utils

Usage

Import 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';

API Documentation

Classes

BaseErrorError

Base error class that all custom errors in this library extend from. Provides a flag to identify errors from this library.

InvalidInputErrorBaseError

Error class for invalid input errors. Extends BaseError to provide a specific error type for input validation failures.

TimeoutErrorError

Error class for timeout operations. Automatically generates a detailed message with timing information.

Constants

raisenever

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.

Functions

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 batchSize items.

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.

BaseError ⇐ Error

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

new exports.BaseError()

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

new exports.InvalidInputError()

Example

throw new InvalidInputError('User ID must be a positive number');

raise ⇒ never

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:

  • Error Always 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'));

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.

Kind: global constant
Example

booleanAsStringSchema.parse('true'); // returns true
booleanAsStringSchema.parse('false'); // returns false
booleanAsStringSchema.parse('yes'); // throws ZodError

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.

Kind: global constant
Example

nonEmptyStringSchema.parse('hello'); // returns 'hello'
nonEmptyStringSchema.parse(''); // throws ZodError with 'This field cannot be empty'

numberAsStringSchema : z.ZodSchema.<number>

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 ZodError

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.

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 false

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.

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)
  })
});

getErrorMessage(error) ⇒ string

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'

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.

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' }]

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.

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());
}

findOrThrow(arr, predicate) ⇒ T

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:

  • Error If 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 found

firstOrThrow(items) ⇒ T

Returns 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:

  • Error If 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 0

indexOrThrow(items, index) ⇒ T

Returns 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:

  • Error If 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 -1

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.

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 execution

sleep(ms) ⇒ Promise.<void>

Asynchronously 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);
}

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.

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[]

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.

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();

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.

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]

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.

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'

batchArray(array, batchSize) ⇒ Array.<Array.<T>>

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']]

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.

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 ≤ 5

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.

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']

groupBy(array, getKey, initialValue) ⇒ Record.<Key, Array.<T>>

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' },
//   ],
// };

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.

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]

roundToDecimals(value, decimals) ⇒ number

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.14

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.

Kind: global function
Returns: number - The parsed number.
Throws:

  • Error When 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: Infinity

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.

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 }]

createRange(length) ⇒ Array.<number>

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:

  • Error If 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 Error

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.

Kind: global function
Returns: function - A function that returns the singleton value, fetching it if necessary.
Throws:

  • Error If 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()]);

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.

Kind: global function
Returns: function - A function that returns the singleton value, fetching it if necessary.
Throws:

  • Error If 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 valid

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.

Kind: global function
Throws:

  • Error The single error if only one handler fails.
  • AggregateError If multiple handlers fail.
Param Type Description
handlers Set.<Handler.<TParams>> Set of handler functions to call.
params TParams Parameters to pass to each handler.

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.

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();

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.

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 subscriber

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.

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 }

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.

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 }

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.

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' }

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.

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' }

Development

Scripts

  • npm test - Run all tests
  • npm run lint - Lint the source code
  • npm run build - Build the library
  • npm run format - Format code with Prettier
  • npm run updateReadme - Generate README documentation from JSDoc comments
  • npm run checks - Check format, run lint, tests and build
  • npm run dev - Format files, lint, test, build and regenerate README file

Publish new version of npm package

  • Run npm run new-version [patch | minor | major]
  • Run npm publish --dry-run and verify output
  • Run npm publish

Design Principles

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

License

MIT

About

Reusable typescript utility functions.

Resources

Stars

4 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages