@pawells/typescript-common
v2.2.0
Published
Shared TypeScript utility library
Downloads
3,044
Maintainers
Readme
@pawells/typescript-common
Description
Shared TypeScript utility library providing strongly-typed, well-tested utility functions across eight domains: array, asserts, boolean, enum, function, lru-cache, object, string, and time. All functions are documented with JSDoc, fully typed, and tested to 80% coverage across all metrics.
Requirements
- Node.js: 22.0.0 or later
- TypeScript: 6.0.0 or later (if consuming from source)
Local Development
During local development, the package exports a local condition that resolves to TypeScript source directly without requiring a build step. This enables fast iteration when developing consuming packages.
To use the local condition in your tsconfig.json, ensure your resolver is configured to recognize the @pawells/typescript-common-workspace condition:
{
"compilerOptions": {
"moduleResolution": "bundler",
"customConditions": ["@pawells/typescript-common-workspace"]
}
}Installation
Install from npm:
npm install @pawells/typescript-commonOr with yarn:
yarn add @pawells/typescript-commonQuick Start
All exports are available from the main entry point or from domain-specific entry points for tree-shaking.
Array Domain
import { ArrayChunk, ArrayFilter, ArrayShuffle, Unique } from '@pawells/typescript-common';
const items = [1, 2, 3, 4, 5];
const chunked = ArrayChunk(items, 2); // [[1, 2], [3, 4], [5]]
const filtered = ArrayFilter([1, 2, 3, 4], (x) => x > 2); // [3, 4]
const shuffled = ArrayShuffle([1, 2, 3]); // Random order
const unique = Unique([1, 2, 2, 3]); // [1, 2, 3]Asserts Domain
import { AssertString, AssertNumber, AssertArray } from '@pawells/typescript-common';
AssertString(value); // Throws if value is not a string
AssertNumber(42); // Passes
AssertArray([1, 2, 3]); // PassesBoolean Domain
import { AssertBoolean } from '@pawells/typescript-common';
AssertBoolean(true); // Passes
AssertBoolean('not a boolean'); // ThrowsEnum Domain
import { EnumKeys, EnumValues, ValidateEnumValue, EnumSafeValue } from '@pawells/typescript-common';
enum Color {
Red = 'RED',
Green = 'GREEN',
Blue = 'BLUE',
}
const keys = EnumKeys(Color); // ['Red', 'Green', 'Blue']
const values = EnumValues(Color); // ['RED', 'GREEN', 'BLUE']
const isValid = ValidateEnumValue(Color, 'RED'); // true
const safe = EnumSafeValue(Color, 'INVALID', Color.Red); // Color.RedFunction Domain
import { Memoize, Debounce, Throttle, Once, Compose } from '@pawells/typescript-common';
// Memoization
const expensiveCalc = Memoize((n: number) => n * n);
expensiveCalc(4); // Computed: 16
expensiveCalc(4); // Cached: 16
// Debouncing
const handleSearch = Debounce((query: string) => console.log(query), 300);
handleSearch('a');
handleSearch('ab');
handleSearch('abc'); // Only this logs after 300ms
// Throttling
const handleResize = Throttle(() => console.log('resized'), 100);
// Single execution
const initialize = Once(() => console.log('init'));
initialize(); // logs
initialize(); // no-op
// Function composition
const add = (x: number) => x + 1;
const double = (x: number) => x * 2;
const composed = Compose(double, add);
composed(5); // (5 + 1) * 2 = 12LRU Cache Domain
import { LRUCache } from '@pawells/typescript-common';
const cache = new LRUCache<string, number>(2);
cache.set('a', 1);
cache.set('b', 2);
cache.set('c', 3); // Evicts 'a' (least recently used)
console.log(cache.get('a')); // undefined
console.log(cache.get('b')); // 2Number Domain
import { AssertNumber, AssertFinite } from '@pawells/typescript-common';
AssertNumber(42); // Passes
AssertNumber('not a number'); // ThrowsObject Domain
import {
ObjectClone,
ObjectEquals,
ObjectFilter,
ObjectPick,
ObjectOmit,
ObjectMerge,
ObjectHash,
} from '@pawells/typescript-common';
const original = { a: 1, b: { c: 2 } };
const cloned = ObjectClone(original);
const obj1 = { x: 1 };
const obj2 = { x: 1 };
console.log(ObjectEquals(obj1, obj2)); // true
const filtered = ObjectFilter({ a: 1, b: 2, c: 3 }, (v) => v > 1); // { b: 2, c: 3 }
const picked = ObjectPick({ a: 1, b: 2, c: 3 }, ['a', 'b']); // { a: 1, b: 2 }
const omitted = ObjectOmit({ a: 1, b: 2, c: 3 }, ['c']); // { a: 1, b: 2 }
const merged = ObjectMerge({ a: 1 }, { b: 2 }); // { a: 1, b: 2 }
const hash = ObjectHash({ a: 1, b: 2 }); // 'e4f3...'String Domain
import {
CamelCase,
PascalCase,
KebabCase,
SnakeCase,
EscapeHTML,
TruncateString,
StringEquals,
} from '@pawells/typescript-common';
console.log(CamelCase('hello-world')); // 'helloWorld'
console.log(PascalCase('hello-world')); // 'HelloWorld'
console.log(KebabCase('helloWorld')); // 'hello-world'
console.log(SnakeCase('helloWorld')); // 'hello_world'
console.log(EscapeHTML('<script>alert("xss")</script>')); // '<script>...'
console.log(TruncateString('Hello World', 8)); // 'Hello...'
console.log(StringEquals('hello', 'HELLO', true)); // true (case-insensitive)Time Domain
import { ElapsedTime, Stopwatch } from '@pawells/typescript-common';
// Elapsed time value object
const elapsed = new ElapsedTime(5000); // 5 seconds
console.log(elapsed.seconds()); // 5
console.log(elapsed.toString()); // '5.00s'
// Stopwatch for timing events
const stopwatch = new Stopwatch();
stopwatch.start();
// ... do work ...
stopwatch.stop();
console.log(stopwatch.elapsed().toString()); // Duration of workAPI Reference
Array
| Symbol | Description |
|--------|-------------|
| ArrayChunk | Splits an array into fixed-size chunks |
| ArrayCompact | Removes null and undefined values from an array |
| ArrayContains | Checks if array contains element matching predicate |
| ArrayDifference | Returns elements in first array but not in second |
| ArrayFilter | Filters array by object criteria or predicate function |
| ArrayFlatten | Flattens nested arrays to specified depth |
| ArrayGroupBy | Groups array elements by a key function |
| ArrayIntersection | Returns elements present in all arrays |
| ArrayPartition | Splits array into two based on predicate |
| ArrayRange | Generates array of numbers in range |
| ArraySample | Returns random element(s) from array |
| ArrayShuffle | Returns shuffled copy of array |
| ArraySortBy | Sorts array by key function with optional comparator |
| ArrayCountBy | Counts elements grouped by key function |
| ArrayZip | Combines multiple arrays element-wise |
| Unique | Returns array with duplicate elements removed |
| TPredicate | Type for predicate function: (value: T) => boolean |
| TTransform | Type for transform function: (input: T) => U |
| TComparator | Type for comparator: (a: T, b: T) => number |
| TEqualityComparator | Type for equality: (a: T, b: T) => boolean |
Asserts
| Symbol | Description |
|--------|-------------|
| AssertEquals | Asserts two values are strictly equal |
| AssertNotEquals | Asserts two values are not strictly equal |
| AssertNull | Asserts value is null |
| AssertNotNull | Asserts value is not null |
| AssertPredicate | Asserts value satisfies predicate function |
| AssertIsType | Asserts value is of specific type |
| AssertInstanceOf | Asserts value is instance of class/constructor |
| AssertFunction | Asserts value is a function |
| AssertSymbol | Asserts value is a symbol |
| AssertExtends | Asserts value extends interface type |
| AssertArray | Asserts value is an array |
| AssertBoolean | Asserts value is a boolean |
| AssertNumber | Asserts value is a number |
| AssertFinite | Asserts value is a finite number |
| AssertObject | Asserts value is a plain object |
| AssertString | Asserts value is a string |
| AssertStringNotEmpty | Asserts value is non-empty string |
| AssertObjectHasProperty | Asserts object has property (including inherited) |
| AssertObjectHasOwnProperty | Asserts object has own property |
| NullError | Custom error for null assertion failure |
| NotNullError | Custom error for not-null assertion failure |
| PredicateError | Custom error for predicate assertion failure |
| TypeGuardError | Custom error for type guard assertion failure |
| InstanceOfError | Custom error for instanceof assertion failure |
| ExtendsError | Custom error for type extends assertion failure |
Boolean
| Symbol | Description |
|--------|-------------|
| AssertBoolean | Asserts value is a boolean |
Enum
| Symbol | Description |
|--------|-------------|
| EnumKeys | Returns array of enum keys |
| EnumValues | Returns array of enum values |
| EnumEntries | Returns array of [key, value] tuples |
| EnumKeyByValue | Looks up enum key by value |
| ValidateEnumValue | Checks if value is valid enum member |
| EnumSafeValue | Returns value if valid enum member, else fallback |
Function
| Symbol | Description |
|--------|-------------|
| Debounce | Delays function execution until after time period with no calls |
| Throttle | Limits function execution to at most once per time period |
| Memoize | Caches function results by serialized arguments (LRU eviction) |
| Once | Returns wrapper that executes function at most once |
| Compose | Creates right-to-left function composition |
| Sleep | Returns promise that resolves after delay |
⚠️ Security Warning — Memoize
Do not memoize functions with sensitive parameters (passwords, tokens, API keys). The cache stores return values keyed by serialized arguments, which could expose sensitive data if the cache is inspected or if the key function inadvertently includes sensitive data.
For functions handling sensitive data, consider:
- Not memoizing at all
- Using a custom key function that excludes sensitive parameters
- Implementing manual cache invalidation after processing sensitive data
See JSDoc
@warningin source for full details.
LRU Cache
| Symbol | Description |
|--------|-------------|
| LRUCache | Generic Least Recently Used cache with fixed capacity |
⚠️ Security Warning — LRU Cache
Do not cache sensitive objects (API keys, tokens, passwords, PII). Cache entries remain in memory until evicted or cleared. If the cache is inspected (via debugger, memory dump, or compromised process), sensitive values will be exposed.
For sensitive data, prefer:
- Ephemeral processing without caching
- Implementing automatic expiration
- Secure clearing (e.g., overwrite before eviction)
See JSDoc
@warningin source for full details.
Number
| Symbol | Description |
|--------|-------------|
| AssertNumber | Asserts value is a number |
| AssertFinite | Asserts value is a finite number |
Object
| Symbol | Description |
|--------|-------------|
| ObjectClone | Deep clones object with circular reference detection |
| TransformObject | Transforms object using visitor pattern |
| ObjectEquals | Deep equality comparison for objects |
| ObjectFilter | Filters object properties by predicate |
| FilterObject | Variant of ObjectFilter |
| ObjectFilterCached | Filters object with caching |
| MapObject | Maps object values by transform function |
| MapObjectCached | Maps object with caching |
| ObjectHash | Generates hash for object |
| ObjectGetPropertyByPath | Gets property value by dot-notation path |
| ObjectSetPropertyByPath | Sets property value by dot-notation path |
| ObjectSortKeys | Returns object with keys sorted |
| ObjectFromKeyValuePairs | Creates object from [key, value] tuples |
| ObjectToKeyValuePairs | Converts object to [key, value] tuples |
| ObjectPick | Returns new object with selected keys |
| ObjectOmit | Returns new object without selected keys |
| ObjectMerge | Shallowly merges objects |
| IsObject | Type guard for plain objects |
| ObjectInvert | Inverts object keys and values |
| ObjectFlatten | Flattens nested object to dot-notation keys |
| ObjectDiff | Computes differences between two objects |
| ObjectHasCircularReference | Detects circular references |
| CreateJsonCircularReplacer | Creates replacer for JSON.stringify with circular refs |
| IsPropertyKeySafe | Checks if property key is safe (not prototype-pollution) |
| IsPropertyPathSafe | Checks if property path is safe |
| SanitizePropertyKey | Removes dangerous characters from key |
| FilterDangerousKeys | Filters dangerous keys from object |
| CreateCircularReferenceDetector | Creates detector for circular references |
| IsInputSafe | Comprehensive input safety check |
String
| Symbol | Description |
|--------|-------------|
| CamelCase | Converts string to camelCase |
| PascalCase | Converts string to PascalCase |
| KebabCase | Converts string to kebab-case |
| SnakeCase | Converts string to snake_case |
| EscapeHTML | Escapes HTML special characters |
| EscapeNewlines | Escapes newline characters for safe logging |
| StripHTML | Removes HTML tags from string |
| FormatString | Formats string using template parameters |
| TruncateString | Truncates string to max length with ellipsis |
| PadString | Pads string to length with character |
| Pluralize | Returns plural form based on count |
| WordCount | Counts words in string |
| CountOccurrences | Counts occurrences of substring |
| StringEquals | Case-sensitive or case-insensitive equality |
| IsEmpty | Checks if string is empty or whitespace only |
| AssertString | Asserts value is a string |
| AssertStringNotEmpty | Asserts value is non-empty string |
Error
| Symbol | Description |
|--------|-------------|
| GetErrorMessage | Safely extracts a message string from an unknown error value |
| GetErrorStack | Safely extracts a stack trace string from an unknown error value |
Time
| Symbol | Description |
|--------|-------------|
| ElapsedTime | Value object representing duration in milliseconds |
| Stopwatch | Utility for recording timestamped events and intervals |
| StopwatchEntry | Represents single stopwatch event (start, stop, lap, etc.) |
Iterators
| Symbol | Description |
|--------|-------------|
| FilteredIterator | Async generator that filters array elements based on a predicate and optional filter criteria |
Zod Utilities
Pre-built Zod schemas and types for common runtime validation scenarios.
| Symbol | Description |
|--------|-------------|
| OBJECT_ID_SCHEMA | Zod schema for MongoDB ObjectId validation (24-char hex string) |
| TObjectId | Type inferred from OBJECT_ID_SCHEMA; represents valid ObjectId string |
| SEMVER_SCHEMA | Zod schema for semantic version validation; transforms to SemVer instance |
| TZodObjectSchema | Type for Zod object schema instances; result of z.object() |
| JSON_SERIALIZABLE_SCHEMA | Zod schema for generic JSON-serializable values (primitives, arrays, objects) |
| TJSONSerializable | Recursive type for JSON-serializable values (excludes undefined and functions) |
| JSON_OBJECT_SCHEMA | Zod schema for JSON objects with string keys and serializable values |
| JSON_DATE_SCHEMA | Zod schema for date strings; transforms to Date instances |
License
MIT — See LICENSE for details.
