import type {ArraySplice} from './array-splice'; import type {ExactKey, IsArrayReadonly, NonRecursiveType, SetArrayAccess, ToString} from './internal'; import type {IsEqual} from './is-equal'; import type {IsNever} from './is-never'; import type {LiteralUnion} from './literal-union'; import type {Paths} from './paths'; import type {SharedUnionFieldsDeep} from './shared-union-fields-deep'; import type {SimplifyDeep} from './simplify-deep'; import type {UnknownArray} from './unknown-array'; /** Omit properties from a deeply-nested object. It supports recursing into arrays. It supports removing specific items from an array, replacing each removed item with unknown at the specified index. Use-case: Remove unneeded parts of complex objects. Use [`Omit`](https://www.typescriptlang.org/docs/handbook/utility-types.html#omittype-keys) if you only need one level deep. @example ``` import type {OmitDeep} from 'type-fest'; type Info = { userInfo: { name: string; uselessInfo: { foo: string; }; }; }; type UsefulInfo = OmitDeep; // type UsefulInfo = { // userInfo: { // name: string; // }; // }; // Supports removing multiple paths type Info1 = { userInfo: { name: string; uselessField: string; uselessInfo: { foo: string; }; }; }; type UsefulInfo1 = OmitDeep; // type UsefulInfo1 = { // userInfo: { // name: string; // }; // }; // Supports array type A = OmitDeep<[1, 'foo', 2], 1>; // type A = [1, unknown, 2]; // Supports recursing into array type Info1 = { address: [ { street: string }, { street2: string, foo: string }; ]; } type AddressInfo = OmitDeep; // type AddressInfo = { // address: [ // { // street: string; // }, // { // street2: string; // }; // ]; // }; ``` @category Object @category Array */ export type OmitDeep, string>> = SimplifyDeep< SharedUnionFieldsDeep< {[P in PathUnion]: OmitDeepWithOnePath}[PathUnion] >, UnknownArray>; /** Omit one path from the given object/array. */ type OmitDeepWithOnePath = T extends NonRecursiveType ? T : T extends UnknownArray ? SetArrayAccess, IsArrayReadonly> : T extends object ? OmitDeepObjectWithOnePath : T; /** Omit one path from the given object. */ type OmitDeepObjectWithOnePath = P extends `${infer RecordKeyInPath}.${infer SubPath}` ? { [Key in keyof ObjectT]: IsEqual> extends true ? ExactKey extends infer RealKey ? RealKey extends keyof ObjectT ? OmitDeepWithOnePath : ObjectT[Key] : ObjectT[Key] : ObjectT[Key] } : ExactKey extends infer Key ? IsNever extends true ? ObjectT : Key extends PropertyKey ? Omit : ObjectT : ObjectT; /** Omit one path from from the given array. It replaces the item to `unknown` at the given index. @example ``` type A = OmitDeepArrayWithOnePath<[10, 20, 30, 40], 2>; //=> type A = [10, 20, unknown, 40]; ``` */ type OmitDeepArrayWithOnePath = // Handle paths that are `${number}.${string}` P extends `${infer ArrayIndex extends number}.${infer SubPath}` // If `ArrayIndex` is equal to `number` ? number extends ArrayIndex ? Array, SubPath>> // If `ArrayIndex` is a number literal : ArraySplice, SubPath>]> // If the path is equal to `number` : P extends `${infer ArrayIndex extends number}` // If `ArrayIndex` is `number` ? number extends ArrayIndex ? [] // If `ArrayIndex` is a number literal : ArraySplice : ArrayType;