/** Mark some properties as required, leaving others unchanged */ export type MarkRequired = Omit & Required>; /** * Helper type to deeply recurse an object and return a structure with the flattened keypath and type * * Scalar array types are returned as the scalar type (i.e. the array is dropped) * * The `D` and `DA` generics are used to limit the depth of recursion. See https://stackoverflow.com/a/76315151 */ export type ToPaths = D extends DA['length'] ? unknown : T extends Record ? { [K in keyof T]: K extends string ? ToPaths : never; }[keyof T] : T extends (infer U)[] ? ToPaths : { path: P extends `${infer Q}.` ? Q : never; type: T; }; /** Convert output of `ToPaths` to an object type */ export type FromPaths = { [P in T['path']]: Extract['type']; }; /** Flatten an object to string keyPath (i.e. { "foo.bar.baz": number }) */ export type FlattenObject> = FromPaths>; /** Make composite types user friendly in the editor by constructing a new type with object keys */ export type Remap = T extends infer O ? { [Key in keyof O]: O[Key]; } : never; /** Deeply mark all nullable properties as optional */ export type DeepOptionalNullable = Remap<{ [Key in keyof TObject as null extends TObject[Key] ? Key : never]?: TObject[Key]; } & { [Key in keyof TObject as null extends TObject[Key] ? never : Key]: TObject[Key] extends Record ? DeepOptionalNullable : TObject[Key] extends (infer U extends Record)[] ? DeepOptionalNullable[] : TObject[Key]; }>;