All essential TypeScript types in one place providing 70+ utility types and helper functions.
—
Runtime functions that complement the type system, providing assertions, factories, and helper utilities. These are actual JavaScript functions that work at runtime alongside the TypeScript type system.
Runtime function that helps assert condition. When condition is falsy, it throws an error with Assertion Error: ${message}.
function assert(condition: any, message?: string): asserts condition;Usage Example:
import { assert } from "ts-essentials";
function processUser(user: unknown) {
assert(user && typeof user === "object", "User must be an object");
assert("id" in user, "User must have an id");
assert("name" in user, "User must have a name");
// TypeScript now knows user is an object with id and name properties
console.log(user.id, user.name); // Type-safe access
}
// Usage in validation
function divide(a: number, b: number): number {
assert(b !== 0, "Division by zero is not allowed");
return a / b; // Safe to divide since b is not 0
}
// Custom assertion messages
function validateConfig(config: any) {
assert(config, "Configuration is required");
assert(config.apiKey, "API key is missing from configuration");
assert(typeof config.timeout === "number", "Timeout must be a number");
}Runtime class instance type that helps check exhaustiveness for value. When value isn't never, it shows TypeScript error.
class UnreachableCaseError extends Error {
constructor(value: never);
}Usage Example:
import { UnreachableCaseError } from "ts-essentials";
type Status = "loading" | "success" | "error";
function handleStatus(status: Status): string {
switch (status) {
case "loading":
return "Loading...";
case "success":
return "Success!";
case "error":
return "Error occurred";
default:
// This ensures exhaustive checking
throw new UnreachableCaseError(status);
}
}
// If you add a new status type, TypeScript will error at the UnreachableCaseError line
type ExtendedStatus = "loading" | "success" | "error" | "pending";
function handleExtendedStatus(status: ExtendedStatus): string {
switch (status) {
case "loading":
return "Loading...";
case "success":
return "Success!";
case "error":
return "Error occurred";
// Missing "pending" case
default:
// TypeScript error: Argument of type 'string' is not assignable to parameter of type 'never'
throw new UnreachableCaseError(status);
}
}Runtime function that validates that type of value matches Constraint without changing resulting type of value. This is a ponyfill for TypeScript's satisfies operator.
function createFactoryWithConstraint<Constraint>(): <T extends Constraint>(value: T) => T;Usage Example:
import { createFactoryWithConstraint } from "ts-essentials";
// Define a constraint interface
interface ApiEndpoint {
path: string;
method: "GET" | "POST" | "PUT" | "DELETE";
handler: (req: any) => any;
}
// Create a factory that ensures objects satisfy the constraint
const createEndpoint = createFactoryWithConstraint<ApiEndpoint>();
// Usage - type is preserved while ensuring constraint satisfaction
const userEndpoint = createEndpoint({
path: "/users",
method: "GET",
handler: (req) => ({ users: [] }),
// Can include additional properties not in constraint
middleware: ["auth", "logging"]
});
// userEndpoint has the exact type including the middleware property
// But TypeScript ensures it satisfies the ApiEndpoint constraint
// Error example - missing required properties
// const invalidEndpoint = createEndpoint({
// path: "/invalid"
// // Error: Property 'method' is missing
// });
// Configuration validation example
interface DatabaseConfig {
host: string;
port: number;
database: string;
}
const createDbConfig = createFactoryWithConstraint<DatabaseConfig>();
const prodConfig = createDbConfig({
host: "prod-db.example.com",
port: 5432,
database: "myapp",
// Additional properties are preserved
ssl: true,
maxConnections: 100
});Runtime function that validates that type of actual equals to Expected. Otherwise shows TypeScript error.
function isExact<Expected>(): <T>(actual: T) => T extends Expected
? Expected extends T
? T
: never
: never;Usage Example:
import { isExact } from "ts-essentials";
// Create exact type checker
const checkExactUser = isExact<{ id: number; name: string }>();
// Valid - exact match
const validUser = checkExactUser({ id: 1, name: "Alice" });
// Invalid - missing property (TypeScript error)
// const invalidUser1 = checkExactUser({ id: 1 }); // Error
// Invalid - extra property (TypeScript error)
// const invalidUser2 = checkExactUser({ id: 1, name: "Alice", email: "alice@example.com" }); // Error
// Usage in testing
function testExactType<T>(value: T, expected: T): void {
const checker = isExact<T>();
checker(value); // Ensures exact type match
}
// Configuration validation
interface AppConfig {
apiUrl: string;
timeout: number;
retries: number;
}
const validateExactConfig = isExact<AppConfig>();
function loadConfig(config: unknown): AppConfig {
// This ensures config matches AppConfig exactly
return validateExactConfig(config as AppConfig);
}Runtime function that does nothing with arguments _args. Useful for default callbacks and placeholders.
function noop(..._args: any[]): void;Usage Example:
import { noop } from "ts-essentials";
// Default callback parameter
interface Options {
onSuccess?: (data: any) => void;
onError?: (error: Error) => void;
}
function processData(data: any, options: Options = {}) {
const { onSuccess = noop, onError = noop } = options;
try {
const result = transformData(data);
onSuccess(result);
} catch (error) {
onError(error as Error);
}
}
// Event handler placeholder
class EventEmitter {
private handlers: Map<string, Function> = new Map();
on(event: string, handler: Function = noop) {
this.handlers.set(event, handler);
}
emit(event: string, ...args: any[]) {
const handler = this.handlers.get(event) || noop;
handler(...args);
}
}
// Development vs production logging
const logger = process.env.NODE_ENV === "production"
? { log: noop, error: noop, warn: noop }
: console;
logger.log("This only logs in development");
// Conditional operations
function setupFeature(enabled: boolean, callback: () => void = noop) {
if (enabled) {
callback();
}
}
setupFeature(false); // No error, noop is used as defaultCombine utility functions for robust error handling and type safety:
import { assert, UnreachableCaseError, createFactoryWithConstraint, isExact, noop } from "ts-essentials";
// Comprehensive validation pipeline
interface UserData {
id: number;
email: string;
role: "admin" | "user" | "guest";
}
const createUser = createFactoryWithConstraint<UserData>();
const validateExactUser = isExact<UserData>();
function processUserData(data: unknown): UserData {
// Runtime assertion
assert(data && typeof data === "object", "Data must be an object");
assert("id" in data && typeof data.id === "number", "Invalid user ID");
assert("email" in data && typeof data.email === "string", "Invalid email");
assert("role" in data, "Role is required");
// Exact type validation
const validatedData = validateExactUser(data as UserData);
// Constraint satisfaction
return createUser(validatedData);
}
// Exhaustive pattern matching with error handling
function getUserPermissions(role: UserData["role"]): string[] {
switch (role) {
case "admin":
return ["read", "write", "delete", "manage"];
case "user":
return ["read", "write"];
case "guest":
return ["read"];
default:
throw new UnreachableCaseError(role);
}
}
// Safe callback execution
function executeCallback<T extends any[]>(
callback: ((...args: T) => void) | undefined,
...args: T
): void {
const safeCallback = callback || noop;
try {
safeCallback(...args);
} catch (error) {
console.error("Callback execution failed:", error);
}
}
// Type-safe factory with validation
function createValidatedFactory<T>(
validator: (value: unknown) => value is T
) {
const factory = createFactoryWithConstraint<T>();
return function(value: unknown): T {
assert(validator(value), "Validation failed");
return factory(value as T);
};
}Install with Tessl CLI
npx tessl i tessl/npm-ts-essentials