core-ts-utils
v1.2.0
Published
A modern, lightweight, and type-safe collection of utility functions for TypeScript and JavaScript projects
Maintainers
Readme
core-ts-utils
A modern, lightweight, and type-safe collection of utility functions for TypeScript and JavaScript projects. Tree-shakable and fully documented with zero dependencies.
Features
- Zero Dependencies - Lightweight and minimal
- Tree-Shakable - Import only what you need
- Type-Safe - Written in TypeScript with comprehensive type definitions
- Well Documented - Every function includes JSDoc with examples
- Modern ESM & CJS - Supports both ES modules and CommonJS
- Browser & Node.js - Works in all JavaScript environments
Installation
npm install core-ts-utils
# or
yarn add core-ts-utils
# or
pnpm add core-ts-utilsQuick Start
import { debounce, chunk, deepClone, isEmail } from "core-ts-utils";
// Debounce a function
const handleResize = debounce(() => console.log("Resized!"), 300);
window.addEventListener("resize", handleResize);
// Split array into chunks
const numbers = [1, 2, 3, 4, 5, 6];
console.log(chunk(numbers, 2)); // [[1, 2], [3, 4], [5, 6]]
// Deep clone objects
const original = { user: { name: "John", age: 30 } };
const clone = deepClone(original);
// Validate email
console.log(isEmail("[email protected]")); // trueTable of Contents
- Function Utilities
- Array Utilities
- Object Utilities
- String Utilities
- Validation
- Browser Utilities
- Async Utilities
API Documentation
Function Utilities
debounce(fn, delay)
Creates a debounced function that delays execution until after delay milliseconds have elapsed since the last invocation.
const searchAPI = debounce((query: string) => {
fetch(`/api/search?q=${query}`);
}, 300);
// Only calls API once after user stops typing for 300ms
searchInput.addEventListener("input", (e) => searchAPI(e.target.value));throttle(fn, limit)
Creates a throttled function that only invokes fn at most once per every limit milliseconds.
const trackScroll = throttle(() => {
console.log("Scroll position:", window.scrollY);
}, 1000);
// Logs at most once per second while scrolling
window.addEventListener("scroll", trackScroll);memoize(fn)
Caches function results based on arguments to avoid expensive recomputations.
const fibonacci = memoize((n: number): number => {
if (n <= 1) return n;
return fibonacci(n - 1) + fibonacci(n - 2);
});
fibonacci(40); // Computes once
fibonacci(40); // Returns cached result instantlyonce(fn)
Ensures a function can only be called once, subsequent calls return the first result.
const initialize = once(() => {
console.log("Initializing...");
return { initialized: true };
});
initialize(); // Logs "Initializing..." and returns result
initialize(); // Returns same result without loggingcurry(fn)
Transforms a function into a sequence of functions, each taking a single argument.
const add = (a: number, b: number, c: number) => a + b + c;
const curriedAdd = curry(add);
const add5 = curriedAdd(5);
const add5And10 = add5(10);
console.log(add5And10(3)); // 18compose(...fns)
Composes functions from right to left.
const double = (x: number) => x * 2;
const addOne = (x: number) => x + 1;
const square = (x: number) => x * x;
const compute = compose(square, double, addOne);
console.log(compute(3)); // ((3 + 1) * 2)² = 64pipe(...fns)
Composes functions from left to right.
const double = (x: number) => x * 2;
const addOne = (x: number) => x + 1;
const square = (x: number) => x * x;
const compute = pipe(addOne, double, square);
console.log(compute(3)); // ((3 + 1) * 2)² = 64partial(fn, ...args)
Partially applies arguments to a function.
const greet = (greeting: string, name: string) => `${greeting}, ${name}!`;
const sayHello = partial(greet, "Hello");
console.log(sayHello("Alice")); // "Hello, Alice!"
console.log(sayHello("Bob")); // "Hello, Bob!"Array Utilities
chunk(array, size)
Splits an array into chunks of specified size.
const items = [1, 2, 3, 4, 5, 6, 7];
console.log(chunk(items, 3)); // [[1, 2, 3], [4, 5, 6], [7]]
// Useful for pagination
const pages = chunk(products, 10); // 10 items per pageflatten(array, depth?)
Flattens nested arrays to specified depth (default: 1).
const nested = [1, [2, [3, [4]]]];
console.log(flatten(nested)); // [1, 2, [3, [4]]]
console.log(flatten(nested, 2)); // [1, 2, 3, [4]]
console.log(flatten(nested, Infinity)); // [1, 2, 3, 4]groupBy(array, iteratee)
Groups array elements by a key or function result.
const users = [
{ name: "Alice", age: 25 },
{ name: "Bob", age: 30 },
{ name: "Charlie", age: 25 }
];
// Group by property
console.log(groupBy(users, "age"));
// { '25': [{ name: 'Alice', age: 25 }, { name: 'Charlie', age: 25 }],
// '30': [{ name: 'Bob', age: 30 }] }
// Group by function
console.log(groupBy(users, (u) => u.name[0]));
// { 'A': [...], 'B': [...], 'C': [...] }uniqueBy(array, iteratee)
Returns unique elements based on a key or function.
const items = [
{ id: 1, name: "A" },
{ id: 2, name: "B" },
{ id: 1, name: "C" }
];
console.log(uniqueBy(items, "id"));
// [{ id: 1, name: "A" }, { id: 2, name: "B" }]Object Utilities
deepClone(obj)
Creates a deep copy of an object.
const original = { user: { name: "John", preferences: { theme: "dark" } } };
const clone = deepClone(original);
clone.user.preferences.theme = "light";
console.log(original.user.preferences.theme); // "dark" (unchanged)Note: Uses JSON serialization. Does not support functions, undefined, Date, Map, Set, or circular references.
pick(obj, keys)
Creates an object with only specified keys.
const user = { id: 1, name: "John", email: "[email protected]", password: "secret" };
const publicUser = pick(user, ["id", "name", "email"]);
// { id: 1, name: "John", email: "[email protected]" }omit(obj, keys)
Creates an object excluding specified keys.
const user = { id: 1, name: "John", email: "[email protected]", password: "secret" };
const publicUser = omit(user, ["password"]);
// { id: 1, name: "John", email: "[email protected]" }merge(target, ...sources)
Deeply merges objects.
const defaults = { theme: "light", fontSize: 14, features: { search: true } };
const userSettings = { theme: "dark", features: { notifications: true } };
const settings = merge(defaults, userSettings);
// { theme: "dark", fontSize: 14, features: { search: true, notifications: true } }isEmpty(value)
Checks if a value is empty (null, undefined, empty string, array, or object).
console.log(isEmpty(null)); // true
console.log(isEmpty("")); // true
console.log(isEmpty([])); // true
console.log(isEmpty({})); // true
console.log(isEmpty([1, 2])); // falseString Utilities
capitalize(str)
Capitalizes the first letter of a string.
console.log(capitalize("hello world")); // "Hello world"
console.log(capitalize("HELLO")); // "HELLO"camelCase(str)
Converts string to camelCase.
console.log(camelCase("hello-world")); // "helloWorld"
console.log(camelCase("Hello World")); // "helloWorld"
console.log(camelCase("hello_world_test")); // "helloWorldTest"kebabCase(str)
Converts string to kebab-case.
console.log(kebabCase("helloWorld")); // "hello-world"
console.log(kebabCase("Hello World")); // "hello-world"snakeCase(str)
Converts string to snake_case.
console.log(snakeCase("helloWorld")); // "hello_world"
console.log(snakeCase("Hello World")); // "hello_world"truncate(str, length, suffix?)
Truncates string to specified length with optional suffix.
console.log(truncate("Hello World", 8)); // "Hello..."
console.log(truncate("Hello World", 8, "…")); // "Hello W…"
console.log(truncate("Hi", 10)); // "Hi" (no truncation needed)template(str, data)
Simple string interpolation with template variables.
const greeting = template("Hello, {{name}}! You have {{count}} messages.", {
name: "Alice",
count: 5
});
// "Hello, Alice! You have 5 messages."Validation
isEmail(str)
Validates email addresses.
console.log(isEmail("[email protected]")); // true
console.log(isEmail("invalid@")); // false
console.log(isEmail("not-an-email")); // falseisURL(str)
Validates URLs.
console.log(isURL("https://example.com")); // true
console.log(isURL("http://localhost:3000/path")); // true
console.log(isURL("not a url")); // falseisNumeric(value)
Checks if value is numeric.
console.log(isNumeric(123)); // true
console.log(isNumeric("123")); // true
console.log(isNumeric("123.45")); // true
console.log(isNumeric("abc")); // falseBrowser Utilities
cookies
Simple cookie management API.
// Set a cookie
cookies.set("theme", "dark", { expires: 7, path: "/" });
// Get a cookie
const theme = cookies.get("theme"); // "dark"
// Delete a cookie
cookies.delete("theme");Options:
expires: Number (days) | Date | stringpath: string (default: "/")domain: stringsecure: booleansameSite: "strict" | "lax" | "none"
storage
Enhanced localStorage wrapper with expiration and object support.
// Set with expiration (5 minutes)
storage.set("user", { id: 1, name: "John" }, 5 * 60 * 1000);
// Get with default value
const user = storage.get("user", { id: 0, name: "Guest" });
// Remove
storage.remove("user");
// Clear all
storage.clear();queryParams
URL query parameter utilities.
// Get parameter from current URL
const userId = queryParams.get("id");
// Get all parameters
const params = queryParams.getAll(); // { id: "123", page: "2" }
// Set parameter
queryParams.set("page", "3"); // Updates URL
// Remove parameter
queryParams.remove("id");Async Utilities
sleep(ms)
Promise-based delay.
async function demo() {
console.log("Start");
await sleep(1000); // Wait 1 second
console.log("After 1 second");
}retry(fn, options)
Retry async operations with exponential backoff.
const fetchData = () => fetch("/api/data").then(r => r.json());
const data = await retry(fetchData, {
maxAttempts: 5,
initialDelay: 100,
maxDelay: 10000,
factor: 2,
onRetry: (error, attempt) => {
console.log(`Attempt ${attempt} failed:`, error.message);
}
});promisify(fn)
Converts callback-style functions to promises.
import { readFile } from "fs";
const readFileAsync = promisify(readFile);
const content = await readFileAsync("file.txt", "utf8");parallel(tasks, limit?)
Executes async tasks in parallel with optional concurrency limit.
const tasks = [
() => fetch("/api/user/1"),
() => fetch("/api/user/2"),
() => fetch("/api/user/3")
];
// Run all in parallel
const results = await parallel(tasks);
// Limit to 2 concurrent requests
const results = await parallel(tasks, 2);randomId(length?)
Generates a random alphanumeric ID.
console.log(randomId()); // "a7b3x9k2" (default: 8 chars)
console.log(randomId(16)); // "3k9mz7q1p5n8x2w4"TypeScript Support
All utilities are written in TypeScript and include comprehensive type definitions:
import { chunk, groupBy, retry } from "core-ts-utils";
// Full type inference
const numbers: number[] = [1, 2, 3, 4, 5];
const chunks: number[][] = chunk(numbers, 2);
// Generic type support
interface User {
id: number;
role: string;
}
const users: User[] = [...];
const byRole: Record<string, User[]> = groupBy(users, "role");
// Async types
const fetchUser = async (): Promise<User> => { ... };
const user: User = await retry(fetchUser);Browser Compatibility
- Modern browsers (ES2022+)
- Node.js 14+
- Supports both ESM and CommonJS
Bundle Size
The package is designed to be tree-shakable. Import only what you need:
// Import specific utilities (recommended)
import { debounce, chunk } from "core-ts-utils";
// Or import everything (not recommended for production)
import * as utils from "core-ts-utils";Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
License
MIT © Hrithik Agarwal
Author
Developed and maintained by Hrithik Agarwal
- GitHub: @hrithik-infinite
- LinkedIn: Hrithik Agarwal
- Email: [email protected]
Support
If you find this package helpful, please consider:
- Starring the repository on GitHub
- Reporting issues or suggesting features
- Contributing to the codebase
