Yevhen Klymentiev
dark
light
console
darkness
y.klymentiev@gmail.com
Reusable Snippets|Practical utility code for everyday use — custom-built and ready to share

flattenObject

Recursively flattens a nested object using dot notation for keys.

TypeScript
Copied!
1/**
2 * Recursively flattens a nested object using dot notation for keys.
3 *
4 * @param obj - The object to flatten.
5 * @param prefix - Internal use only: prefix for nested keys.
6 * @returns A new flat object with dot-separated keys.
7 */
8export function flattenObject(obj: any, prefix = ''): Record<string, any> {
9  return Object.keys(obj).reduce((acc, key) => {
10    const fullKey = prefix ? `${prefix}.${key}` : key;
11    const value = obj[key];
12
13    if (value && typeof value === 'object' && !Array.isArray(value)) {
14      Object.assign(acc, flattenObject(value, fullKey));
15    } else {
16      acc[fullKey] = value;
17    }
18
19    return acc;
20  }, {} as Record<string, any>);
21}
  • Recursive Deep Flattening

    Converts arbitrarily nested objects into a flat structure using dot notation, making deeply nested data easier to work with.

  • Preserves Key Hierarchy

    Encodes the original structure into dot-separated keys, allowing for accurate reconstruction or reference.

  • Handles Arbitrary Nesting Levels

    Works on deeply nested objects without hardcoded depth limits or special cases.

  • Clean and Extensible

    Minimal and readable logic that can be extended to support arrays, custom delimiters, or filters if needed.

Tests | Examples

TypeScript
Copied!
1test('flattenObject - flattens a simple nested object', () => {
2  const input = { a: { b: 1 } };
3  const expected = { 'a.b': 1 };
4  expect(flattenObject(input)).toEqual(expected);
5});
6
7test('flattenObject - handles multiple levels of nesting', () => {
8  const input = { a: { b: { c: { d: 2 } } } };
9  const expected = { 'a.b.c.d': 2 };
10  expect(flattenObject(input)).toEqual(expected);
11});
12
13test('flattenObject - ignores arrays (treats them as values)', () => {
14  const input = { a: [1, 2], b: { c: 3 } };
15  const expected = { 'a': [1, 2], 'b.c': 3 };
16  expect(flattenObject(input)).toEqual(expected);
17});
18
19test('flattenObject - preserves primitive values', () => {
20  const input = { a: 1, b: 'text', c: false };
21  const expected = { a: 1, b: 'text', c: false };
22  expect(flattenObject(input)).toEqual(expected);
23});
24
25test('flattenObject - handles empty object', () => {
26  expect(flattenObject({})).toEqual({});
27});
28
29test('flattenObject - handles null and undefined properly', () => {
30  const input = { a: null, b: undefined, c: { d: null } };
31  const expected = { a: null, b: undefined, 'c.d': null };
32  expect(flattenObject(input)).toEqual(expected);
33});

Common Use Cases

  • Form Handling and Validation

    Flatten nested form state to easily bind inputs, validate fields, or send structured payloads.

  • API Interactions

    Convert complex payloads into flat structures for compatibility with systems that don't support nested keys.

  • Configuration Management

    Flatten deeply nested config files or environment overrides for simpler parsing or injection.

  • Logging and Debugging

    Log complex objects in a flattened format for better visibility in structured logs.

  • Data Normalization

    Preprocess JSON or database records for storage in flat-schema systems like spreadsheets or key-value stores.

Codebase: Utilities -> Objects -> flattenObject | Yevhen Klymentiev