export type OptionalizeAux = Id< { [K in KeysWithUndefined]?: Optionalize } & { [K in Exclude>]: T[K] extends ObjectLiteral ? Optionalize : T[K] } > /** * Makes all of properties in T optional when they're null | undefined * it is recursive */ export type Optionalize = T extends object ? T extends unknown[] ? number extends T['length'] ? T[number] extends object ? Array> : T : Partial : OptionalizeAux : T export type KeysWithUndefined = { [K in keyof T]-?: undefined extends T[K] ? K : null extends T[K] ? K : never }[keyof T] /** * alternative to 'object' or '{}' * @example: * export const o: ObjectLiteral = [] as object; // error * export const o: object = []; // no error */ export type ObjectLiteral = { [K in PropertyKey]: T } /** * object identity type */ export type Id = T extends infer U ? { [K in keyof U]: U[K] } : never /** Array with no utilty methods, aka Object.create(null) */ export interface ArrayWithNoPrototype { [index: number]: T | ArrayWithNoPrototype } /** * Allows any type but T * it is recursive * @example * export type RequestData = Record>; */ export type AnythingBut = Exclude< | Primitive | { [K in PropertyKey]: AnythingBut } | ArrayWithNoPrototype< | Primitive | { [K in PropertyKey]: AnythingBut } >, T > /** Non object primitives */ export type Primitive = string | number | symbol | bigint | boolean | undefined | null // | object <- don't make object a primitive