defaultsDeep()
defaultsDeep<
T>(object, ...sources):T
Recursively assigns source properties to destination only where destination is undefined.
Only undefined values are replaced. null values are preserved.
Type Parametersโ
T: T extends Record<string, unknown>โ
The type of the destination object.
Parametersโ
object: Tโ
The destination object.
sources: ...Record<string, unknown>[]โ
The source objects.
Returns: Tโ
A new object with deep defaults applied (does not mutate original).
Sinceโ
2.0.0
Noteโ
Arrays are replaced, not merged.
Performanceโ
O(nรm) where n = total properties, m = depth.
Also known asโ
defaultsDeep (Lodash, es-toolkit) ยท mergeDeepRight (Ramda) ยท โ (Remeda, Radashi, Effect, Modern Dash, Antfu)
Exampleโ
const target = { a: { b: undefined, c: 3 } };
const source = { a: { b: 2, d: 4 }, e: 5 };
defaultsDeep(target, source);
// => { a: { b: 2, c: 3, d: 4 }, e: 5 }
// null is preserved (not undefined)
defaultsDeep({ a: { b: null } }, { a: { b: 'fallback' } });
// => { a: { b: null } }
// Arrays are replaced, not merged
defaultsDeep({ items: undefined }, { items: [1, 2] });
// => { items: [1, 2] }
How it works?โ
Recursively fills in undefined properties at all nesting levels.
Deep Traversalโ
defaults vs defaultsDeepโ
| defaults | defaultsDeep | |
|---|---|---|
| Scope | Top-level only | All nesting levels |
| Objects | Replaced | Merged recursively |
Use Casesโ
Configuration Merging with nested defaults ๐โ
Merge user configuration with default values recursively. Essential for application configuration systems.
import { defaultsDeep } from "pithos/arkhe/object/defaults-deep";
const defaultConfig = {
server: {
port: 3000,
host: "localhost",
ssl: { enabled: false, cert: null },
},
logging: {
level: "info",
format: "json",
},
cache: {
enabled: true,
ttl: 3600,
},
};
const userConfig = {
server: {
port: 8080,
ssl: { enabled: true },
},
logging: {
level: "debug",
},
};
const config = defaultsDeep(userConfig, defaultConfig);
console.log(config);
// {
// server: { port: 8080, host: "localhost", ssl: { enabled: true, cert: null } },
// logging: { level: "debug", format: "json" },
// cache: { enabled: true, ttl: 3600 }
// }
Theme Customization with partial overrides ๐โ
Apply partial theme overrides to default theme. Critical for customizable UI systems.
import { defaultsDeep } from "pithos/arkhe/object/defaults-deep";
const defaultTheme = {
colors: {
primary: "#007bff",
secondary: "#6c757d",
background: "#ffffff",
text: "#212529",
},
spacing: {
small: "8px",
medium: "16px",
large: "24px",
},
typography: {
fontFamily: "Arial, sans-serif",
fontSize: { base: "16px", heading: "24px" },
},
};
const darkThemeOverrides = {
colors: {
background: "#1a1a1a",
text: "#f0f0f0",
},
};
const darkTheme = defaultsDeep(darkThemeOverrides, defaultTheme);
console.log(darkTheme.colors);
// { primary: "#007bff", secondary: "#6c757d", background: "#1a1a1a", text: "#f0f0f0" }
API Request Options with defaultsโ
Apply default options to API requests. Important for consistent API interactions.
import { defaultsDeep } from "pithos/arkhe/object/defaults-deep";
const defaultOptions = {
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
timeout: 30000,
retry: { attempts: 3, delay: 1000 },
};
function createRequest(url: string, options: Partial<typeof defaultOptions> = {}) {
const finalOptions = defaultsDeep(options, defaultOptions);
return {
url,
...finalOptions,
};
}
const request = createRequest("/api/users", {
headers: { Authorization: "Bearer token" },
retry: { attempts: 5 },
});
console.log(request.headers);
// { "Content-Type": "application/json", Accept: "application/json", Authorization: "Bearer token" }
console.log(request.retry);
// { attempts: 5, delay: 1000 }