export type Nullable = T | null // eslint-disable-next-line @typescript-eslint/no-empty-interface, @typescript-eslint/no-empty-object-type interface DeepReadonlyArray extends ReadonlyArray> {} type DeepReadonlyObject = { readonly [P in keyof T]: DeepReadonly } export type DeepReadonly = T extends (infer R)[] ? DeepReadonlyArray : T extends (...args: any[]) => void ? T : T extends object ? DeepReadonlyObject : T export type DeepPartial = Partial<{ [P in keyof T]: DeepPartial }> export type MergeAndOverride = Own & Omit export type Keys = (keyof T)[] export type ExcludeStrict = Exclude /** * Helper to create type guards for literal unions * * @example * ```ts * const fruit = ['apple', 'banana', 'cherry'] as const; * type Fruit = typeof fruit[number]; * const isFruit = mkLiteralUnionTypeguard(fruit); * * // Usage example: * function eatFood(food: unknown[]) { * food.forEach(item => { * if (isFruit(item)) { * eatFruit(item) * } else { * console.log(`Not fruit ${item}`) * } * }) * } * eatFood(['banana', 'pizza']) * ``` * * @param xs A readonly tuple of allowed values (strings, numbers, or symbols). * @returns A type guard function `(value: unknown) => value is T[number]`. */ export function mkLiteralUnionTypeguard< const T extends readonly (string | number | symbol)[], >(xs: T) { return (v: unknown): v is T[number] => (xs as readonly (string | number | symbol)[]).includes(v as any) }