Skip to content

MergeRecursive Method

The mergeRecursive() method deeply merges the given array or collection with the original collection. Unlike the regular merge method, it recursively merges nested arrays and objects.

Basic Syntax

typescript
collect(items).mergeRecursive(items: array | Collection | object)

Examples

Basic Usage

typescript
import { collect } from 'ts-collect'

// Simple nested objects
const original = collect({
  settings: {
    theme: 'light',
    notifications: {
      email: true,
      push: false
    }
  }
})

const update = {
  settings: {
    notifications: {
      push: true
    }
  }
}

const result = original.mergeRecursive(update)
console.log(result.all())
// {
//   settings: {
//     theme: 'light',
//     notifications: {
//       email: true,
//       push: true
//     }
//   }
// }

Complex Object Merging

typescript
interface DeepConfig {
  database: {
    connection: {
      host: string
      port: number
      credentials?: {
        username: string
        password: string
      }
    }
    pool: {
      min: number
      max: number
    }
  }
  cache: {
    driver: string
    options: Record<string, any>
  }
}

const defaultConfig = collect<DeepConfig>({
  database: {
    connection: {
      host: 'localhost',
      port: 5432,
      credentials: {
        username: 'default',
        password: 'secret'
      }
    },
    pool: {
      min: 2,
      max: 10
    }
  },
  cache: {
    driver: 'redis',
    options: {
      host: 'localhost',
      port: 6379
    }
  }
})

const customConfig = {
  database: {
    connection: {
      host: 'production.db',
      credentials: {
        username: 'prod_user'
      }
    },
    pool: {
      max: 20
    }
  }
}

const finalConfig = defaultConfig.mergeRecursive(customConfig)

Real-world Examples

Application State Management

typescript
interface AppState {
  user: {
    profile: {
      personal: {
        name: string
        email: string
        preferences: {
          theme: string
          language: string
          notifications: {
            email: boolean
            push: boolean
            frequency: string
          }
        }
      }
      professional?: {
        title: string
        department: string
      }
    }
    settings: Record<string, any>
  }
}

class StateManager {
  private state: Collection<AppState>

  constructor() {
    this.state = collect<AppState>({
      user: {
        profile: {
          personal: {
            name: '',
            email: '',
            preferences: {
              theme: 'light',
              language: 'en',
              notifications: {
                email: true,
                push: true,
                frequency: 'daily'
              }
            }
          }
        },
        settings: {}
      }
    })
  }

  updateState(newState: Partial<AppState>) {
    this.state = this.state.mergeRecursive(newState)
    return this.state
  }
}

// Usage
const manager = new StateManager()
manager.updateState({
  user: {
    profile: {
      personal: {
        name: 'John Doe',
        preferences: {
          notifications: {
            push: false
          }
        }
      }
    }
  }
})

Deep Configuration Override

typescript
interface ServiceConfig {
  api: {
    endpoints: {
      [key: string]: {
        url: string
        method: string
        headers?: Record<string, string>
        timeout?: number
      }
    }
    defaults: {
      headers: Record<string, string>
      timeout: number
      retries: {
        count: number
        delay: number
      }
    }
  }
}

const baseConfig = collect<ServiceConfig>({
  api: {
    endpoints: {
      users: {
        url: '/api/users',
        method: 'GET',
        headers: {
          'Content-Type': 'application/json'
        }
      }
    },
    defaults: {
      headers: {
        Accept: 'application/json'
      },
      timeout: 5000,
      retries: {
        count: 3,
        delay: 1000
      }
    }
  }
})

const environmentConfig = {
  api: {
    endpoints: {
      users: {
        url: 'https://prod.api/users',
        timeout: 10000
      }
    },
    defaults: {
      retries: {
        count: 5
      }
    }
  }
}

const finalConfig = baseConfig.mergeRecursive(environmentConfig)

Working with Arrays

typescript
interface Department {
  name: string
  teams: {
    name: string
    members: string[]
  }[]
}

const original = collect<Department>({
  name: 'Engineering',
  teams: [
    {
      name: 'Frontend',
      members: ['Alice', 'Bob']
    },
    {
      name: 'Backend',
      members: ['Charlie']
    }
  ]
})

const update = {
  teams: [
    {
      name: 'Frontend',
      members: ['David']
    }
  ]
}

const merged = original.mergeRecursive(update)

Type Safety

typescript
interface TypedNested {
  level1: {
    level2: {
      value: string
      array: number[]
      options?: {
        enabled: boolean
        settings: Record<string, any>
      }
    }
  }
}

const base = collect<TypedNested>({
  level1: {
    level2: {
      value: 'original',
      array: [1, 2],
      options: {
        enabled: true,
        settings: {
          key1: 'value1'
        }
      }
    }
  }
})

// Type-safe recursive merging
const merged = base.mergeRecursive({
  level1: {
    level2: {
      array: [3],
      options: {
        settings: {
          key2: 'value2'
        }
      }
    }
  }
})

Return Value

  • Returns a new Collection instance containing the recursively merged items
  • Maintains the complete nested structure
  • Arrays are concatenated
  • Objects are deeply merged
  • Original collection remains unchanged

Released under the MIT License.