/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-empty-object-type -- needed */ import {type Primitive} from './Primitive.js'; /** * Same as built-in `Partial`, but works recursively. Useful when 1) you have a config object to which you need to merge another object, which would be a deep partial of a default object, or 2) you need to test or mock complex object, but most of its keys would be redundant for this purpose. * * ```TypeScript * import { DeepPartial } from '@ori/ts-utils'; * import { UiSettings } from './UiSettings'; * * let settings: UiSettings = { * lineNumbers: true, * scrollbar: { * useShadows: false, * vertical: 'visible', * horizontal: 'auto', * }, * minimap: { * enabled: false, * }, * folding: { * enabled: true, * }, * }; * * function updateSettings(newSettings: DeepPartial) { * return { ...settings, ...newSettings }; * } * * settings = updateSettings({ minimap: { enabled: true } }); * ``` * * @typeParam T Base for the new type */ export type DeepPartial = T extends Date | Primitive | RegExp ? T : T extends Map ? DeepPartialMap : T extends Set ? DeepPartialSet : T extends ReadonlyMap ? DeepPartialReadonlyMap : T extends ReadonlySet ? DeepPartialReadonlySet : T extends (...args: any[]) => unknown ? T | undefined : T extends object ? T extends ( Array // Test for arrays/tuples, per https://github.com/microsoft/TypeScript/issues/35156 ) ? I[] extends ( T // Test for arrays (non-tuples) specifically ) ? Array> // Recreate relevant array type to prevent eager evaluation of circular reference : DeepPartialObject // Tuples behave properly : DeepPartialObject : unknown; /** * Helper type for {@link DeepPartial}. */ interface DeepPartialMap extends Map< DeepPartial, DeepPartial > {} /** * Helper type for {@link DeepPartial}. */ interface DeepPartialSet extends Set> {} /** * Helper type for {@link DeepPartial}. */ interface DeepPartialReadonlyMap extends ReadonlyMap< DeepPartial, DeepPartial > {} /** * Helper type for {@link DeepPartial}. */ interface DeepPartialReadonlySet extends ReadonlySet> {} /** * Helper type for {@link DeepPartial}. */ type DeepPartialObject = { [KeyType in keyof ObjectType]?: DeepPartial; };