export type keys = keyof T; export function keys(obj: T): keys[] { return Object.keys(obj) as any; } export type entries = { [K in keyof T]: [K, T[K]] }[keyof T] export function entries(obj: T): entries[]{ return Object.entries(obj) as any; } export type values = T[keyof T]; export function values(obj: T): values[] { return Object.values(obj); } export type fromEntries = { [Entry in TUnion as Entry[0]]: Entry[1] } export function fromEntries(entries: TPair[]): fromEntries { return Object.fromEntries(entries) as any; } type MergeTarget = Source extends Partial ? Target : Target & Source; type CompileArray = Sources extends [...infer Rest, infer Source] ? CompileArray, Rest> : Sources extends [infer Source] ? MergeTarget : Sources extends [] ? Target : Target; // eslint-disable-next-line @typescript-eslint/ban-types export function assign(target: T, ...sources: A): CompileArray { return Object.assign(target, ...sources); } export function assignDeep(target: A, stuff: B): A & B { if (!(target instanceof Object)) { throw new RangeError('this function only useful on things with an Object prototype'); } let current: any = target; while (Reflect.getPrototypeOf(current)?.constructor && Reflect.getPrototypeOf(current)!.constructor !== Object) { current = Reflect.getPrototypeOf(current)!; } Reflect.setPrototypeOf(current, Reflect.getPrototypeOf(stuff)); return Object.assign(target, stuff); }