Skip to content

Instantly share code, notes, and snippets.

@Krishprajapati15
Created May 6, 2025 07:11
Show Gist options
  • Select an option

  • Save Krishprajapati15/91d7bd4852ebd92f72787a1f13b67be6 to your computer and use it in GitHub Desktop.

Select an option

Save Krishprajapati15/91d7bd4852ebd92f72787a1f13b67be6 to your computer and use it in GitHub Desktop.
This TypeScript utility library provides a comprehensive set of tools to enhance your project's readability, maintainability, and type safety. It includes features such as a deepClone function for creating deep copies of objects, a Result type for structured error handling, a deepFreeze function for immutable objects, and a retry utility for han…

🚀 TypeScript Utility Library

Welcome to the TypeScript Utility Library, a collection of reusable, type-safe, and elegant utilities designed to streamline your TypeScript projects. Whether you're handling deep object manipulations, managing asynchronous operations, or ensuring robust type safety, this library has you covered. 🌟


✨ Features

  • Deep Object Manipulations
    Easily clone or freeze deeply nested objects with utilities like deepClone and deepFreeze.

  • Type-Safe Error Handling
    Use the Result type to handle errors gracefully and ensure predictable outcomes.

  • Asynchronous Operation Helpers
    Retry failed promises with retry or add timeouts with withTimeout for better async flow control.

  • Advanced Type Utilities
    Simplify type management with DeepPartial and robust type guards like assertNever.

  • Typed Event Emitters
    Enjoy strongly-typed event handling with the TypedEventEmitter.


📦 Installation

To include this utility library in your project, simply run:

npm install my-ts-utility-library

or

yarn add my-ts-utility-library

🛠️ Usage Examples

1. Deep Clone Objects

import { deepClone } from "my-ts-utility-library";

const original = { name: "Alice", details: { age: 25 } };
const cloned = deepClone(original);

console.log(cloned); // { name: "Alice", details: { age: 25 } }

2. Error Handling with Result

import { Result, ok, fail } from "my-ts-utility-library";

function divide(a: number, b: number): Result<number, string> {
  if (b === 0) return fail("Division by zero");
  return ok(a / b);
}

const result = divide(10, 2);
if (result.ok) {
  console.log("Result:", result.value);
} else {
  console.error("Error:", result.error);
}

3. Retry Asynchronous Operations

import { retry } from "my-ts-utility-library";

const fetchData = async () => {
  // Simulate API call
  if (Math.random() < 0.8) throw new Error("Random failure");
  return "Success!";
};

retry(fetchData, 3, 1000)
  .then(console.log)
  .catch(console.error);

4. Typed Event Emitter

import { TypedEventEmitter } from "my-ts-utility-library";

interface MyEvents {
  data: string;
  error: Error;
}

const emitter = new TypedEventEmitter<MyEvents>();

emitter.on("data", (data) => console.log("Data received:", data));
emitter.emit("data", "Hello, World!");

5. Add Timeout to Promises

import { withTimeout } from "my-ts-utility-library";

const fetchData = async () => {
  await new Promise((r) => setTimeout(r, 3000)); // Simulate delay
  return "Data fetched successfully!";
};

withTimeout(fetchData(), 2000)
  .then(console.log)
  .catch(console.error); // Will throw "Timeout exceeded"

📖 API Documentation

deepClone<T>(obj: T): T

Deeply clones an object.
Parameters:

  • obj - The object to clone.

Returns:
The deeply cloned object.


Result<T, E>

A type-safe way to handle success and failure outcomes.

Example:

  • ok(value: T): Result<T> - Represents a successful result.
  • fail(error: E): Result<never, E> - Represents a failure result.

retry<T>(fn: () => Promise<T>, retries?: number, delay?: number): Promise<T>

Retries a failing asynchronous function.
Parameters:

  • fn - The function to retry.
  • retries - Number of retry attempts (default: 3).
  • delay - Delay between retries in milliseconds (default: 1000).

TypedEventEmitter<Events extends Record<string, any>>

A strongly-typed event emitter.

Methods:

  • on<K extends keyof Events>(event: K, listener: (data: Events[K]) => void): void
  • emit<K extends keyof Events>(event: K, data: Events[K]): void

🛡️ Contributing

We welcome contributions! Here's how you can get involved:

  1. Fork the repository.
  2. Create a new branch for your feature or bug fix.
  3. Submit a pull request with detailed information.

💬 Questions or Feedback?

Feel free to open an issue or start a discussion in the repository. We'd love to hear from you!


🏆 Acknowledgements

Special thanks to all contributors who make this project awesome. ❤️


📄 License

This project is licensed under the MIT License.

/**
* Amazing TypeScript Utility Library
*
* This file contains reusable utility functions and types that make your TypeScript projects
* more robust, type-safe, and fun to work with!
*/
// -----------------------------------
// 1. Typed DeepClone Function
// -----------------------------------
export function deepClone<T>(obj: T): T {
return JSON.parse(JSON.stringify(obj));
}
// Usage Example:
// const original = { name: "Alice", age: 25 };
// const copy = deepClone(original);
// console.log(copy); // { name: "Alice", age: 25 }
// -----------------------------------
// 2. Result Type for Error Handling
// -----------------------------------
export type Result<T, E = Error> = { ok: true; value: T } | { ok: false; error: E };
export function ok<T>(value: T): Result<T> {
return { ok: true, value };
}
export function fail<E>(error: E): Result<never, E> {
return { ok: false, error };
}
// Usage Example:
// function divide(a: number, b: number): Result<number, string> {
// if (b === 0) return fail("Division by zero");
// return ok(a / b);
// }
// const result = divide(10, 2);
// if (result.ok) console.log("Value:", result.value);
// else console.error("Error:", result.error);
// -----------------------------------
// 3. Immutable Deep Freeze Function
// -----------------------------------
export function deepFreeze<T>(obj: T): Readonly<T> {
Object.getOwnPropertyNames(obj).forEach((name) => {
const value = obj[name as keyof T];
if (value && typeof value === "object") {
deepFreeze(value);
}
});
return Object.freeze(obj);
}
// Usage Example:
// const obj = deepFreeze({ name: "Frozen", details: { age: 30 } });
// obj.details.age = 40; // Error: Cannot assign to read-only property
// -----------------------------------
// 4. Partial Deep Utility Type
// -----------------------------------
export type DeepPartial<T> = {
[P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
};
// Usage Example:
// interface User {
// name: string;
// address: {
// city: string;
// zip: string;
// };
// }
// const partialUser: DeepPartial<User> = { address: { city: "New York" } };
// -----------------------------------
// 5. Async Retry Utility
// -----------------------------------
export async function retry<T>(
fn: () => Promise<T>,
retries = 3,
delay = 1000
): Promise<T> {
let attempts = 0;
while (attempts < retries) {
try {
return await fn();
} catch (error) {
if (attempts === retries - 1) throw error;
await new Promise((resolve) => setTimeout(resolve, delay));
}
attempts++;
}
throw new Error("Failed after retries");
}
// Usage Example:
// const fetchData = async () => {
// // Simulate API call
// if (Math.random() < 0.8) throw new Error("Random failure");
// return "Success";
// };
// retry(fetchData, 5, 500)
// .then(console.log)
// .catch(console.error);
// -----------------------------------
// 6. Never Type Guard
// -----------------------------------
export function assertNever(x: never): never {
throw new Error(`Unexpected value: ${x}`);
}
// Usage Example:
// type Status = "success" | "failure";
// function handleStatus(status: Status): void {
// switch (status) {
// case "success":
// console.log("Success!");
// break;
// case "failure":
// console.error("Failure!");
// break;
// default:
// assertNever(status); // Will catch unexpected values at compile-time
// }
// }
// -----------------------------------
// 7. Timeout Wrapper for Promises
// -----------------------------------
export async function withTimeout<T>(promise: Promise<T>, ms: number): Promise<T> {
const timeout = new Promise<never>((_, reject) =>
setTimeout(() => reject(new Error("Timeout exceeded")), ms)
);
return Promise.race([promise, timeout]);
}
// Usage Example:
// const fetchWithTimeout = withTimeout(fetch("https://api.example.com"), 5000);
// -----------------------------------
// 8. Typed Event Emitter
// -----------------------------------
type EventMap = Record<string, any>;
export class TypedEventEmitter<Events extends EventMap> {
private listeners: { [K in keyof Events]?: Array<(data: Events[K]) => void> } = {};
on<K extends keyof Events>(event: K, listener: (data: Events[K]) => void): void {
if (!this.listeners[event]) this.listeners[event] = [];
this.listeners[event]!.push(listener);
}
emit<K extends keyof Events>(event: K, data: Events[K]): void {
this.listeners[event]?.forEach((listener) => listener(data));
}
}
// Usage Example:
// interface MyEvents {
// data: string;
// error: Error;
// }
// const emitter = new TypedEventEmitter<MyEvents>();
// emitter.on("data", (data) => console.log("Data:", data));
// emitter.emit("data", "Hello, World!");
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment