Skip to content

fs-helpers ​

Tree-shakeable utility functions: deep copy, type guards, and case conversion.

bash
npm install @script-development/fs-helpers

What It Does ​

fs-helpers provides a small set of utility functions used across multiple packages and applications. Every function is individually importable — your bundler only includes what you use.

Deep Copy ​

Creates a deep clone of objects, arrays, and dates. Faster than structuredClone for typical application data:

typescript
import {deepCopy} from '@script-development/fs-helpers';

const original = {name: 'Alice', roles: ['admin', 'editor'], createdAt: new Date()};

const copy = deepCopy(original);
copy.roles.push('viewer');

original.roles; // ["admin", "editor"] — unchanged
copy.roles; // ["admin", "editor", "viewer"]

Writable Types ​

deepCopy returns a Writable<T> type — the same shape as the input but with all readonly modifiers removed. This is useful when you need a mutable copy of a readonly object:

typescript
interface User {
    readonly id: number;
    readonly name: string;
}

const user: User = {id: 1, name: 'Alice'};
const mutable = deepCopy(user);
mutable.name = 'Bob'; // allowed — Writable<User> removes readonly

Supported types

deepCopy handles primitives, plain objects, arrays, Date, and null. It does not handle Map, Set, RegExp, functions, or circular references. For those cases, use structuredClone.

Type Guards ​

isExisting ​

Checks whether an object has an id property — useful for distinguishing between new (unsaved) and existing (saved) domain objects:

typescript
import {isExisting} from '@script-development/fs-helpers';

interface User {
    id: number;
    name: string;
}

type NewUser = Omit<User, 'id'>;

function saveUser(user: User | NewUser) {
    if (isExisting(user)) {
        // TypeScript knows: user is User (has id)
        updateUser(user.id, user);
    } else {
        // TypeScript knows: user is NewUser (no id)
        createUser(user);
    }
}

Case Conversion ​

Convert between camelCase and snake_case with full type safety:

typescript
import {toCamelCaseTyped, deepCamelKeys, deepSnakeKeys} from '@script-development/fs-helpers';

toCamelCaseTyped ​

Converts a snake_case object to camelCase with preserved TypeScript types:

typescript
interface User {
    firstName: string;
    lastName: string;
    createdAt: string;
}

// API returns snake_case
const apiResponse = {first_name: 'Alice', last_name: 'Smith', created_at: '2026-01-01'};

const user = toCamelCaseTyped<User>(apiResponse);
// { firstName: "Alice", lastName: "Smith", createdAt: "2026-01-01" }
// Typed as User — not Record<string, unknown>

deepCamelKeys / deepSnakeKeys ​

Deep conversion for nested objects (re-exported from string-ts):

typescript
const apiData = {user_name: 'Alice', user_settings: {dark_mode: true, font_size: 14}};

const camelData = deepCamelKeys(apiData);
// { userName: "Alice", userSettings: { darkMode: true, fontSize: 14 } }

const snakeData = deepSnakeKeys(camelData);
// Back to { user_name: "Alice", user_settings: { dark_mode: true, font_size: 14 } }

API Reference ​

Functions ​

FunctionSignatureDescription
deepCopy<T>(toCopy: T) => Writable<T>Deep clone for objects, arrays, dates
isExisting<T extends {id: number}>(obj) => obj is TType guard for objects with an id
toCamelCaseTyped<T extends object>(data) => TType-safe snake_case to camelCase
deepCamelKeys(obj) => DeepCamelKeysDeep snake_case to camelCase
deepSnakeKeys(obj) => DeepSnakeKeysDeep camelCase to snake_case

Types ​

TypeDescription
Writable<T>Removes all readonly modifiers from T
DeepSnakeKeys<T>Recursively converts keys to snake_case

Built by Script Development & Back to Code