@pawells/typescript-common
v1.4.1
Published
Shared TypeScript utility library — array, object, string, time, and enum helpers. ESM-only, no runtime dependencies.
Downloads
2,343
Maintainers
Readme
TypeScript Common Utilities
Shared TypeScript utility library. ESM-only, no runtime dependencies, targets ES2022.
Installation
npm install @pawells/typescript-common
# or
yarn add @pawells/typescript-commonUsage
All utilities are available as namespace imports or as individual named exports for tree-shaking.
// Namespace import
import {
ArrayUtils, BooleanUtils, NumberUtils,
ObjectUtils, StringUtils, TimeUtils,
EnumUtils, FunctionUtils, AssertsUtils,
} from '@pawells/typescript-common';
ArrayUtils.ArrayChunk([1, 2, 3, 4], 2); // [[1, 2], [3, 4]]
ArrayUtils.AssertArray(value); // throws if not an array
ObjectUtils.IsObject(value); // returns true/false (type-guard)
BooleanUtils.AssertBoolean(value); // throws if not a boolean
NumberUtils.AssertNumber(value, { gte: 0, integer: true });
// Direct named import (tree-shakeable)
import { ArrayChunk, ObjectPick, CamelCase, Sleep, AssertString, LRUCache } from '@pawells/typescript-common';Features & Patterns
Readonly Array Support
All array utilities accept readonly T[] arrays, enabling zero-copy usage with frozen constants:
const colors = Object.freeze(['red', 'green', 'blue']); // readonly string[]
ArrayChunk(colors, 2); // Works without casting!
ArrayFilter(colors, c => c.length > 3); // ✓ No type errorsCustom RNG for Deterministic Testing
ArraySample and ArrayShuffle accept an optional custom RNG function for reproducible randomization:
const seededRng = Mulberry32(42); // Your seeded PRNG
ArrayShuffle([1, 2, 3], seededRng); // Same output every time
ArraySample([1, 2, 3], 2, seededRng); // Deterministic sampling
// Without RNG, defaults to Math.random() for normal usage
ArrayShuffle([1, 2, 3]); // Random shufflePredicate Functions in ObjectFilter
Filter by predicate functions in addition to equality checks:
const user = { name: 'John', age: 30, active: true };
// Basic equality filtering
ObjectFilter(user, { name: 'John' }); // true
// Predicate functions as filter values
ObjectFilter(user, { age: (v) => v > 18 }); // true
ObjectFilter(user, { age: (v) => v < 18 }); // false
// Mix predicates and values
ObjectFilter(user, {
active: true,
age: (v) => v >= 21
}); // true
// Supports dot notation with predicates
const order = { user: { age: 25 }, total: 100 };
ObjectFilter(order, {
'user.age': (v) => v >= 21,
'total': (v) => v > 50
}); // trueAPI
Array utilities — ArrayUtils
| Export | Description |
|--------|-------------|
| ArrayChunk(array, size) | Split an array into chunks of a given size |
| ArrayContains(array, predicate) | Check if any element satisfies a predicate |
| ArrayFilter(array, predicate) | Type-safe array filter |
| ArrayGroupBy(array, keyFn) | Group array elements by a key function |
| ArrayIntersection(a, b) | Return elements present in both arrays |
| ArrayShuffle(array, rng?) | Return a shuffled copy of an array (optional custom RNG for deterministic results) |
| ArraySample(array, n?, rng?) | Random element or n random elements (optional custom RNG for deterministic results) |
| Unique(array) | Remove duplicate values |
| ArrayDifference(a, b) | Elements in a not present in b |
| ArrayFlatten(array, depth?) | Flatten a nested array to a given depth |
| ArrayCompact(array) | Remove null/undefined, narrowing the type |
| ArrayPartition(array, predicate) | Split into [matches, rest] |
| ArrayZip(...arrays) | Zip multiple arrays into tuples |
| ArrayRange(start, end, step?) | Generate a numeric sequence |
| ArraySortBy(array, keyFn, direction?) | Immutable sort by a computed key |
| ArrayCountBy(array, keyFn) | Count elements per group key |
| AssertArray(value, args?, exception?) | Assert value is an array (with optional size constraints) |
| AssertArray2D(value, args?, exception?) | Assert value is a rectangular 2D array |
| AssertArrayNotEmpty(value, exception?) | Assert array has at least one element |
| AssertArrayAll(array, predicate, exception?) | Assert every element satisfies a predicate |
| AssertArrayAny(array, predicate, exception?) | Assert at least one element satisfies a predicate |
Boolean utilities — BooleanUtils
| Export | Description |
|--------|-------------|
| AssertBoolean(value, exception?) | Assert value is a boolean primitive |
Number utilities — NumberUtils
| Export | Description |
|--------|-------------|
| AssertNumber(value, args?, exception?) | Assert value is a number with optional range/type constraints (finite, integer, gt, gte, lt, lte, eq) |
Object utilities — ObjectUtils
| Export | Description |
|--------|-------------|
| IsObject(value) | Type-guard: returns true if value is a non-null, non-array object |
| ObjectClone(obj) | Deep-clone an object |
| ObjectEquals(a, b) | Deep equality check |
| ObjectFilter(obj, filter, options?) | Filter object by property values or predicate functions (supports dot notation, deep equality, case-insensitive matching, and predicate functions) |
| ObjectFilterCached(obj, predicate) | Cached filter for repeated operations |
| FilterObject(obj, keys) | Keep only specified keys |
| ObjectPick(obj, keys) | Pick a subset of keys |
| ObjectOmit(obj, keys) | Omit specified keys |
| ObjectMerge(target, ...sources) | Deep merge objects |
| MapObject(obj, fn) | Map over object values |
| MapObjectCached(obj, fn) | Cached map for repeated operations |
| TransformObject(obj, fn) | Transform object entries |
| ObjectHash(obj) | Compute a stable hash of an object |
| ObjectSortKeys(obj) | Return object with keys sorted |
| ObjectFromKeyValuePairs(pairs) | Build an object from [key, value] pairs |
| ObjectToKeyValuePairs(obj) | Convert an object to [key, value] pairs |
| ObjectGetPropertyByPath(obj, path) | Get a nested property by dot-path |
| ObjectSetPropertyByPath(obj, path, value) | Set a nested property by dot-path |
| ObjectInvert(obj) | Swap keys and values |
| ObjectFlatten(obj, separator?) | Flatten nested object to dot-separated keys |
| ObjectDiff(objA, objB) | Compute added/removed/changed keys between two objects |
| ObjectHasCircularReference(obj) | Detect circular references in an object |
| CreateJsonCircularReplacer(placeholder?) | Create a JSON.stringify replacer that handles circular refs |
| AssertObject(value, exception?) | Assert value is a plain object (not null, array, or function), narrowing to Record<string, unknown> |
| AssertObjectHasProperty(value, property, exception?) | Assert object has an inherited or own property |
| AssertObjectHasOwnProperty(value, property, exception?) | Assert object has a direct own property |
| AssertObjectPropertyNotNull(value, property, exception?) | Assert object property is not null/undefined |
String utilities — StringUtils
| Export | Description |
|--------|-------------|
| CamelCase(str) | Convert a string to camelCase |
| CAPITALIZE(str) | Capitalize the first letter of a string |
| PASCAL_CASE(str) | Convert a string to PascalCase |
| KEBAB_CASE(str) | Convert a string to kebab-case |
| SNAKE_CASE(str) | Convert a string to snake_case |
| SCREAMING_SNAKE_CASE(str) | Convert a string to SCREAMING_SNAKE_CASE |
| FormatString(template, values) | Simple string template formatting |
| TruncateString(str, maxLength, ellipsis?) | Truncate a string with ellipsis |
| PadString(str, length, char?, padEnd?) | Pad a string to a specified length |
| EscapeHTML(str) | Escape HTML special characters |
| StripHTML(str) | Remove all HTML tags from a string |
| Pluralize(word, count, plural?) | Return singular or plural form based on count |
| WordCount(str) | Count the number of words in a string |
| CountOccurrences(str, substr) | Count non-overlapping occurrences of a substring |
| REVERSE_STRING(str) | Reverse a string |
| SLUGIFY(str) | Convert a string to a URL-friendly slug |
| IS_BLANK_STRING(str) | Check if a string is empty or whitespace-only |
| IS_HEX_STRING(str) | Check if a string is a valid hexadecimal value |
| AssertString(value, exception?) | Assert value is a string primitive |
| AssertStringNotEmpty(value, exception?) | Assert value is a non-empty, non-whitespace string |
| AssertStringMatches(value, regex, exception?) | Assert string matches a regular expression |
Time utilities — TimeUtils
| Export | Description |
|--------|-------------|
| ElapsedTime | Class for measuring elapsed time with human-readable output |
| FormatElapsedTime(ms, options?) | Format milliseconds using concise format |
| Stopwatch | Lap-based stopwatch for benchmarking |
Enum utilities — EnumUtils
| Export | Description |
|--------|-------------|
| EnumKeys(enumObj) | Get keys of a TypeScript enum |
| EnumValues(enumObj) | Get values of a TypeScript enum |
| EnumEntries(enumObj) | Get key-value pairs of a TypeScript enum |
| ValidateEnumValue(enumObj, value) | Check if a value is a valid enum member |
| EnumKeyByValue(enumObj, value) | Look up an enum key by its value |
| EnumSafeValue(enumObj, value) | Return the value if valid, or undefined |
Function utilities — FunctionUtils
| Export | Description |
|--------|-------------|
| Debounce(fn, ms) | Delay execution until ms ms after the last call |
| Throttle(fn, ms) | Limit execution to at most once per ms ms |
| Memoize(fn, keyFn?) | Cache results by serialised arguments |
| Once(fn) | Execute a function at most once, caching the result |
| Pipe(...fns) | Compose functions left-to-right |
| Compose(...fns) | Compose functions right-to-left |
| Sleep(ms) | Return a Promise that resolves after ms ms |
LRU Cache — LRUCache
| Export | Description |
|--------|-------------|
| LRUCache<K, V> | Generic Least Recently Used cache with configurable capacity |
const cache = new LRUCache<string, number>(100);
cache.set('key', 42);
cache.get('key'); // 42 (marks as recently used)
cache.has('key'); // true
cache.clear(); // removes all entriesAssertion utilities — AssertsUtils
Cross-cutting assertions not tied to a single type, plus the shared assertion infrastructure.
| Export | Description |
|--------|-------------|
| AssertEquals(value, expected, exception?) | Assert two values are deeply equal |
| AssertNotEquals(value, expected, exception?) | Assert two values are not deeply equal |
| AssertNull(value, exception?) | Assert value is null or undefined |
| AssertNotNull(value, exception?) | Assert value is neither null nor undefined |
| AssertPredicate(value, predicate, exception?) | Assert a custom predicate holds |
| AssertIsType(value, typeGuard, exception?) | Assert via a type-guard function |
| AssertInstanceOf(value, constructor, exception?) | Assert value is an instance of a constructor |
| AssertFunction(value, exception?) | Assert value is a function |
| AssertSymbol(value, exception?) | Assert value is a symbol |
| AssertExtends(derived, base, exception?) | Assert one class extends another |
| ThrowException(exception) | Throw using an IAssertException config object |
| SetExceptionClass(exception, class, force?) | Configure the error class for an assertion |
| SetExceptionMessage(exception, message, force?) | Configure the error message for an assertion |
All type-specific assertions (AssertArray, AssertBoolean, AssertNumber, AssertObject (throwing), AssertString, etc.) are also accessible through AssertsUtils as a single convenience namespace.
Note: AssertObject is a throwing assertion available in both ObjectUtils and AssertsUtils (narrows to Record<string, unknown>). Use ObjectUtils.IsObject for a non-throwing boolean type-guard that returns true/false.
Error classes
BaseError, ValidationError, AssertionError, InvalidArgumentError, NotFoundError, NotSupportedError, BufferOverflowError, ArrayError, BooleanError, NumberError, NumberRangeError, ObjectError, ObjectPropertyError, StringError, NullError, NotNullError, PredicateError, TypeGuardError, InstanceOfError, FunctionError, SymbolError, ExtendsError.
Development
yarn install # Install dependencies
yarn build # Compile TypeScript (tsconfig.build.json) → ./build/
yarn dev # Build + run
yarn watch # Watch mode
yarn typecheck # Type check without building
yarn lint # ESLint
yarn lint:fix # ESLint with auto-fix
yarn test # Run tests
yarn test:ui # Interactive Vitest UI
yarn test:coverage # Tests with coverage reportRequirements
- Node.js >= 22.0.0
License
MIT — See LICENSE for details.
