export type PrimitiveType = undefined | null | number | string | boolean | symbol export type NonFunctionType = PrimitiveType | NonFunctionObject export type NonFunctionObject = ( { bind?: NonFunctionType } | { apply?: NonFunctionType } | { call?: NonFunctionType }); export interface ModulePlainMethod { (this: C, ...args: never[]): unknown } export interface ModuleArrowMethod { (this: unknown, that: C, ...args: never[]): unknown prototype?: PrimitiveType } export type ModuleMethod = ModulePlainMethod | ModuleArrowMethod export interface ModuleLoadizable { [key: string]: ModuleMethod | NonFunctionType } export type LoadedProxy, C = M extends ModuleLoadizable ? R : never> = { [K in string & keyof M]: ( M[K] extends (this: unknown, that: C, ...args: infer A) => infer R ? /* arrow */ (this: unknown, ...args: A) => R : M[K] extends (this: C, ...args: infer A) => infer R ? /* normal */ (this: unknown, ...args: A) => R : M[K] & NonFunctionType ) } export interface ModuleSpecMap { [key: string]: ModuleSpec } export interface ModuleSpec { members: object children: ModuleSpecMap } type MemberType = SpecToType< DescendContextMixin & Pick>, MS['children'][K]> interface DescendContextMixin { _: LoadedProxy, this> __: LoadedProxy, C> } type SpecToType = MS['members'] & { [K in keyof MS['children']]: MemberType } export type ModuleHierarchy = { [K in keyof MSM]: SpecToType };