Skip to content

Object Utilities

Object utilities provide robust tools to manipulate, compare, and traverse objects in a type-safe, ergonomic way. Use these helpers for cloning, diffing, nested path access, caching, and more.

📚 Quick Reference

Problem

Implement 📚 quick reference in a production-friendly way with @vielzeug/toolkit while keeping setup and cleanup explicit.

Runnable Example

The snippet below is copy-paste runnable in a TypeScript project with @vielzeug/toolkit installed.

  • stash: Key-value cache with automatic GC and observer support.
  • deepClone: Deep clone nested values and common JS structures.
  • defaults: Apply fallback values for undefined keys.
  • diff: Compare two objects and return the structural differences.
  • entries: Typed wrapper for Object.entries.
  • filterValues: Filter object keys by value predicate.
  • fromEntries: Typed wrapper for Object.fromEntries.
  • has: Type-safe key existence check.
  • invert: Invert key-value pairs.
  • keys: Typed wrapper for Object.keys.
  • mapKeys: Transform object keys.
  • mapValues: Transform object values.
  • deepMerge and shallowMerge: Merge multiple objects.
  • pick: Create a new object with only selected keys.
  • omit: Create a new object excluding selected keys.
  • parseJSON: Safely parse JSON strings with optional fallback value.
  • get: Safely access nested properties using dot-notation strings.
  • prune: Recursively remove null/undefined/empty values.
  • seek: Recursively search nested values by similarity threshold.
  • values: Typed wrapper for Object.values.

💡 Practical Examples

Cloning & Diffing

ts
import { deepClone, diff } from '@vielzeug/toolkit';

const config = { api: { host: 'localhost', port: 8080 }, flags: { beta: false } };
const finalConfig = deepClone(config);

finalConfig.api.port = 3000;
finalConfig.flags.beta = true;

// Find what changed
const changes = diff(config, finalConfig);
// { api: { port: 3000 }, flags: { beta: true } }

Deep vs Shallow Merge

ts
import { deepMerge, shallowMerge } from '@vielzeug/toolkit';

const base = { api: { host: 'localhost', port: 8080 }, tags: ['core'] };
const override = { api: { port: 3000 }, tags: ['docs'] };

const deep = deepMerge(base, override);
// { api: { host: 'localhost', port: 3000 }, tags: ['core', 'docs'] }

const shallow = shallowMerge(base, override);
// { api: { port: 3000 }, tags: ['docs'] }

console.log(deep, shallow);

Accessing Nested Data

ts
import { get, omit, pick, seek } from '@vielzeug/toolkit';

const data = {
  user: {
    profile: {
      settings: { theme: 'dark' },
    },
  },
};

// Access via path string
const theme = get(data, 'user.profile.settings.theme'); // 'dark'

// Search values anywhere in the object
const hasDark = seek(data, 'dark'); // true

const user = { id: 1, name: 'Alice', role: 'admin', password: 'secret' };
const safe = pick(user, ['id', 'name', 'role']);
const noSecret = omit(user, ['password']);

console.log(theme, hasDark, safe, noSecret);

Pruning & Cleaning

ts
import { prune } from '@vielzeug/toolkit';

// Remove all nulls, undefined, empty strings, and empty objects/arrays
prune({ a: 1, b: null, c: '', d: { e: undefined } }); // { a: 1 }
prune([1, null, '', 2, undefined]); // [1, 2]
prune('  hello  '); // 'hello'
prune('   '); // undefined

Caching

ts
import { stash } from '@vielzeug/toolkit';

const myCache = stash<string>({ hash: (key) => JSON.stringify(key) });
myCache.set(['user', 1], 'John Doe');
myCache.get(['user', 1]); // 'John Doe'
myCache.scheduleGc(['user', 1], 5000); // Auto-delete after 5s
myCache.size(); // 1

🔗 All Object Utilities

Expected Output

  • The example runs without type errors in a standard TypeScript setup.
  • The main flow produces the behavior described in the recipe title.

Common Pitfalls

  • Forgetting cleanup/dispose calls can leak listeners or stale state.
  • Skipping explicit typing can hide integration issues until runtime.
  • Not handling error branches makes examples harder to adapt safely.