import type {BuiltIns} from './internal'; /** Create a deep version of another type where all optional keys are set to also accept `undefined`. Note: This is only needed when the [`exactOptionalPropertyTypes`](https://www.typescriptlang.org/tsconfig#exactOptionalPropertyTypes) TSConfig setting is enabled. Use-cases: - When `exactOptionalPropertyTypes` is enabled, an object like `{a: undefined}` is not assignable to the type `{a?: number}`. You can use `UndefinedOnPartialDeep<{a?: number}>` to make it assignable. @example ``` import type {UndefinedOnPartialDeep} from 'type-fest'; interface Settings { optionA: string; optionB?: number; subOption: { subOptionA: boolean; subOptionB?: boolean; } }; const testSettingsA: Settings = { optionA: 'foo', optionB: undefined, // TypeScript error if `exactOptionalPropertyTypes` is true. subOption: { subOptionA: true, subOptionB: undefined, // TypeScript error if `exactOptionalPropertyTypes` is true }, }; const testSettingsB: UndefinedOnPartialDeep = { optionA: 'foo', optionB: undefined, // 👉 `optionB` can be set to undefined now. subOption: { subOptionA: true, subOptionB: undefined, // 👉 `subOptionB` can be set to undefined now. }, }; ``` */ export type UndefinedOnPartialDeep = // Handle built-in type and function T extends BuiltIns | Function ? T // Handle tuple and array : T extends readonly unknown[] ? UndefinedOnPartialList // Handle map and readonly map : T extends Map ? Map> : T extends ReadonlyMap ? ReadonlyMap> // Handle set and readonly set : T extends Set ? Set> : T extends ReadonlySet ? ReadonlySet> // Handle object : T extends Record ? { [KeyType in keyof T]: undefined extends T[KeyType] ? UndefinedOnPartialDeep | undefined : UndefinedOnPartialDeep } : T; // If T is not builtins / function / array / map / set / object, return T // Handle tuples and arrays type UndefinedOnPartialList = T extends [] ? [] : T extends [infer F, ...infer R] ? [UndefinedOnPartialDeep, ...UndefinedOnPartialDeep] : T extends readonly [infer F, ...infer R] ? readonly [UndefinedOnPartialDeep, ...UndefinedOnPartialDeep] : T extends Array ? Array> : T extends ReadonlyArray ? ReadonlyArray> : never;