export type IteratorProcessAble = Iterable | Record; export type IterCallback, K = T extends Iterable ? number : keyof T & string> = (value: V, key: K, items: T) => C; export type ForEachCallback> = IterCallback; export type Optional = Partial; export type Nullable = { [P in keyof T]: T[P] | null }; export type ExcludeField = { [Property in keyof Type as Exclude]: Type[Property] }; export type RecordTree = Record>; export type Creator = () => T; export type Class = { new(...args: P): T; }; export type ParameterDecorator = (target: T, property: string | symbol, index: number) => void; export type PropertyDecorator = (target: T, property: P) => void; export type MethodDecorator = (target: T, property: P, descriptor: PropertyDescriptor) => void; export type ClassDecorator = (constructor: T) => void; export type UnionToIntersection = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never export type ExtractInstance = T extends Class ? V : never export type Mixed = Mixins extends (infer T)[] ? Class>> : never export function constructor(target: any): T { return target.constructor as any; } export function mixins[], C extends any, P extends any[]>(Base: Class, ...classes: T): Mixed<[Class, ...T]> { const C = class { constructor(...args: P) { const b = new Base(...args); const descriptors = Object.getOwnPropertyDescriptors(b); foreach(descriptors, ['constructor'], (descriptor, key) => { Object.defineProperty(this, key, descriptor); }); for (const C of classes) { const c = new C(); const descriptors = Object.getOwnPropertyDescriptors(c); foreach(descriptors, ['constructor'], (descriptor, key) => { Object.defineProperty(this, key, descriptor); }); } } }; for (let c of [Base, ...classes] as Class[]) { do { // static member let descriptors = Object.getOwnPropertyDescriptors(c); foreach(descriptors, ['name', 'length', 'prototype'], (descriptor, key) => { Object.defineProperty(C, key, descriptor); }); if (c.prototype) { // method descriptors = Object.getOwnPropertyDescriptors(c.prototype); foreach(descriptors, ['constructor'], (descriptor, key) => { Object.defineProperty(C.prototype, key, descriptor); }); } c = Object.getPrototypeOf(c); } while (c != Object.getPrototypeOf(Object)); } // console.log(C.prototype); return C as Mixed<[Class, ...T]>; } export function isset(value: unknown): value is any { return value != null; } export function isString(value: unknown): value is string { return typeof value === 'string'; } export function isNumber(value: unknown): value is number { return typeof value === 'number'; } export function isBoolean(value: unknown): value is boolean { return typeof value === 'boolean'; } export function isArray(value: unknown): value is Array { return Array.isArray(value); } export function isIterable(value: unknown): value is Iterable { return Symbol.iterator in Object(value); } export function isType(value: unknown, type: string) { return {}.toString.call(value) == '[object ' + type + ']'; } export function isObject(value: unknown): value is Record { return isType(value, 'Object'); } export function isFunction(value: unknown): value is Function { return isType(value, 'Function'); } export function foreach, K = T extends Iterable ? number : keyof T & string>(data: IteratorProcessAble & T | undefined, callback: ForEachCallback): void; export function foreach, K = T extends Iterable ? number : keyof T & string>(data: IteratorProcessAble & T | undefined, excludes: K[], callback: ForEachCallback): void; export function foreach, K = T extends Iterable ? number : keyof T & string>(data: IteratorProcessAble & T | undefined, ...args: any[]): void { if (typeof data === 'undefined') { return; } let callback: ForEachCallback; let excludes: K[]; if (args.length === 1) { excludes = []; callback = args[0]; } else { excludes = args[0]; callback = args[1]; } if (isIterable(data)) { return Array.from(data).forEach((value, index, array) => { const key: any = index; if (!excludes.includes(key)) { callback(value, key, array as any); } }); } return Object.keys(data).forEach((index) => { const key: any = index; if (!excludes.includes(key)) { callback(data[key], key, data); } }); }