Skip to content

defaultsDeep

Recursively assigns default values from source to target. For each property, if the target’s value is undefined (or missing), the source’s value is used. When both sides have plain objects at the same key, they are merged recursively. Existing null, 0, "", false, and array values in the target are preserved.

import { defaultsDeep } from "1o1-utils";
import { defaultsDeep } from "1o1-utils/defaults-deep";
function defaultsDeep({ target, source }: DefaultsDeepParams): Record<string, unknown>
NameTypeRequiredDescription
targetRecord<string, unknown>YesThe base object whose defined values win
sourceRecord<string, unknown>YesThe object supplying defaults

Record<string, unknown> — A new object (neither input is mutated).

defaultsDeep({
target: { db: { port: 5432 } },
source: { db: { port: 3306, host: "localhost" }, debug: false },
});
// => { db: { port: 5432, host: "localhost" }, debug: false }
defaultsDeep({
target: { tags: [1, 2] },
source: { tags: [3, 4, 5] },
});
// => { tags: [1, 2] } — arrays in target are preserved, not merged
  • Throws if target is not a plain object.
  • Throws if source is not a plain object.
  • Only replaces values that are strictly undefinednull, 0, "", and false are preserved.
  • Arrays are treated as leaves — target arrays are preserved and not merged with source arrays.
  • Only merges plain objects recursively; other value types overwrite only when target is undefined.
  • Uses a stack-based (non-recursive) algorithm to avoid stack overflow on deeply nested objects.

deep defaults, nested defaults, fill undefined recursive, fallback object deep

I'm using 1o1-utils (npm: https://www.npmjs.com/package/1o1-utils, GitHub: https://github.com/pedrotroccoli/1o1-utils, LLM context: https://pedrotroccoli.github.io/1o1-utils/llms.txt). Show me how to use defaultsDeep to merge a nested config with default values without overriding user settings