vaco
v3.5.0
Published
some useful tools for programming
Maintainers
Readme
TypeScript Utility Functions
Overview
This repository contains a collection of utility functions written in TypeScript. These functions are designed to handle various tasks such as asynchronous stream control, function control, error handling, functional programming tools, object manipulation, and array operations.
Table of Contents
- Handlers
- Asynchronous Stream Control
- Function Control
- Event Emitter
- Initializer
- Error Handling
- Functional Tools
- Object Logic
- Asynchronous Retry Control
- Array Logic
- Kind Creators
- Usage
Exported Functions
Below is a list of the functions available in this module:
Handlers
ox(): void– A no-operation function, useful as a placeholder or default callback.timeout(ms: number): Promise<void>– Returns a promise that resolves after the specified number of milliseconds.
Asynchronous Stream Control
debounce<T>(fn: T, ms: number): (...args: Parameters<T>) => void– Delays invoking a function untilmsmilliseconds have passed since the last invocation.throttle<T>(fn: T, ms: number): (...args: Parameters<T>) => ReturnType<T>– Ensures a function is invoked at most once everymsmilliseconds.
Function Control
mapFactory<T>(setterFunction: SingleParameter<T>) => typeof setterFunction– Creates a memoized function. For a given input,setterFunctionis called only once to compute the result; subsequent calls with the same input return the cached result. RequiressetterFunctionto accept exactly one argument.collection: Map<Parameters<T>[0], ReturnType<T>>– Provides access to the internal Map that stores the input-output pairs for memoization.mapFactory.reset()– Clears the cache for allmapFactoryinstances.
cache<T>(f: T) => typeof f– Caches the results of a function based on its arguments, optimizing performance for repeated calls with the same inputs.cache.reset()– Clears all cached results.
Event Emitter
Emitter<T extends Record<string, any[]>>– A class for implementing the publish-subscribe pattern.emit<K extends keyof T>(eventName: K, ...args: T[K]): void– Dispatches an event with the specified name and arguments to all registered listeners.on<K extends keyof T>(eventName: K, listener: (...args: T[K]) => void): void– Registers a listener function for the specified event name.off<K extends keyof T>(eventName: K, listenerToRemove: (...args: T[K]) => void): void– Removes a specific listener for the specified event name.once<K extends keyof T>(eventName: K, listener: (...args: T[K]) => void): void– Registers a listener function that will be called only once for the specified event name.
Initializer
Initializer<T extends InitialSetup>(setup: T): PromisifyFunctions<ReturnType<T>>– Manages asynchronous initialization logic. It takes a setup function that defines initialization steps and returns an object with methods that automatically wait for initialization only once to complete before executing.type InitialSetup = ( setInit: (intitialize: () => Promise<void>) => void ) => Record<string, (...args: any[]) => Promise<any> | any>
Error Handling
catchError<T>(fn: T, ...args: Parameters<T>) => [Error, undefined] | [undefined, ReturnType<T>]– Executes a function and returns a tuple:[error, undefined]on failure, or[undefined, result]on success. Handles both synchronous functions and functions returning promises.
Functional Tools
compose<T>(...fns: T): (...args: Parameters<LastT<T>>) => ComposedFn<T>– Composes functions from right to left, creating a single function pipeline.curry<T>(f: T, ...args: Partial<Parameters<T>>) => FinalFnShape<T>– Transforms a function that takes multiple arguments into a sequence of functions that each take a single argument (or a subset of arguments).
Object Logic
clone<T>(obj: T): T– Creates a deep clone of an object or array.isEqual(o1: any, o2: any): boolean– Performs a deep comparison between two values to determine if they are equivalent.isSame(o1: any, o2: any): boolean– Checks if the first object's properties and values are a subset of the second object's properties and values (shallow comparison).
Asynchronous Retry Control
retry<T>(fn: T, retryInterval: number, maxWaitTime: number): (...args: Parameters<T>) => Promise<ReturnType<T>>– Retries an asynchronous function if it fails. It attempts retries atretryIntervalmilliseconds untilmaxWaitTimemilliseconds have passed since the first attempt.
Array Logic
separateArray<T>(ar: readonly T[], fn: (p: T) => boolean): { matches: T[], nonMatches: T[] }– Partitions an array into two arrays based on whether elements satisfy the predicate functionfn.removeDuplicates<T>(ar: T[]): T[]– Returns a new array with duplicate elements removed.
Kind Creators
Utilities for creating and working with "kinded" types (types with a __kind property).
MK<T, K extends string>– A type helper to create a "kinded" type by adding a__kind: Kproperty to typeT.EK<T>– A type helper representing either a kinded typeMK<T, any>or the base typeT.buildMKConverter<T extends MK<any, string>, R>(converter: (val: T, kind: T extends { readonly __kind: infer K } ? K : never) => R): BuildMKC<T, R>– Creates a function that takes a kinded value and its kind, applying the provided converter function.add<T extends number>(a: T, b: T): T– Adds two numbers, preserving the "kind" if they are kinded numbers.minus<T extends number>(a: T, b: T): T– Subtracts the second number from the first, preserving the "kind" if they are kinded numbers.
Usage
Import the necessary functions from the vaco module (adjust the import source based on your project setup) and use them in your TypeScript projects.
// Assuming 'vaco' is the package name or module path
import { debounce, throttle, cache, retry, catchError } from "vaco"
// Example: Debounce
const debouncedLog = debounce(() => console.log("Debounced!"), 500)
debouncedLog() // Called once
debouncedLog() // Called again quickly, resets the timer
// "Debounced!" will log 500ms after the *last* call.
// Example: Cache
const expensiveCalculation = (num: number) => {
console.log(`Calculating for ${num}...`)
return num * 2
}
const cachedCalc = cache(expensiveCalculation)
console.log(cachedCalc(5)) // Calculating for 5... logs 10
console.log(cachedCalc(5)) // Logs 10 (retrieved from cache)
console.log(cachedCalc(10)) // Calculating for 10... logs 20
console.log(cachedCalc(10)) // Logs 20 (retrieved from cache)
// Example: Catch Error
const mightFail = (shouldFail: boolean): Promise<string> => {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (shouldFail) {
reject(new Error("Operation failed!"))
} else {
resolve("Operation succeeded!")
}
}, 100)
})
}
async function runOperation(fail: boolean) {
const [err, result] = await catchError(mightFail, fail)
if (err) {
console.error("Caught error:", err.message)
} else {
console.log("Got result:", result)
}
}
runOperation(false) // Logs: Got result: Operation succeeded!
runOperation(true) // Logs: Caught error: Operation failed!
// Example: Kind Creators
import { MK, add, minus, buildMKConverter } from "vaco"
// Define kinded types for different units
type Cm = MK<number, "cm">
type Mm = MK<number, "mm">
type Meter = MK<number, "meter">
type Second = MK<number, "second">
type Minute = MK<number, "minute">
type VelocityMS = MK<number, "meter/second">
// Create instances of kinded types
const lengthCm = 20 as Cm
const lengthMm = 50 as Mm
const distanceM = 100 as Meter
const timeS = 10 as Second
const timeM = 2 as Minute
// Use kind-safe arithmetic
const totalCm = add(lengthCm, 10 as Cm) // OK
// const invalidAdd = add(lengthCm, lengthMm); // TypeScript Error: Kinds don't match
const remainingCm = minus(lengthCm, 5 as Cm) // OK
// const invalidMinus = minus(lengthMm, timeS); // TypeScript Error: Kinds don't match
// Build a converter function
const convertTimeToSeconds = buildMKConverter<Second | Minute, Second>(
(value, kind) => {
switch (kind) {
case "minute":
return (value * 60) as Second
case "second":
return value // Already in seconds
}
}
)
const timeInSeconds = convertTimeToSeconds(timeM, "minute") // Converts 2 minutes to 120 seconds
// Use kinded types in function signatures for type safety
const calculateVelocity = (distance: Meter, time: Second): VelocityMS => {
return (distance / time) as VelocityMS
}
const velocity = calculateVelocity(distanceM, timeInSeconds)
console.log(`Velocity: ${velocity} m/s`)
// const wrongVelocity = calculateVelocity(distanceM, timeM); // TypeScript Error: timeM is Minute, not SecondThis module provides a comprehensive set of utilities for optimizing function execution, handling errors, managing asynchronous operations, and manipulating data structures.
