import { A } from "ts-toolbelt" ; export declare type SelectKeys < O extends object , M extends any > = { [ K in keyof O ] : { 1 : K ; 0 : never ; } [ A . Is < O [ K ] , M > ] ; } [ keyof O ] ; export type FunctionKeysOf < T extends object > = SelectKeys < T , ( ... args : any ) => any > ; export type FunctionAt < T extends object , K extends FunctionKeysOf < T > > = ( ... args : Parameters < T [ K ] > ) => ReturnType < T [ K ] > ; export type OverrideFunction < S , T extends object , K extends FunctionKeysOf < T > > = ( this : S , oldFn : FunctionAt < T , K > , ... args : Parameters < T [ K ] > ) => ReturnType < T [ K ] > ; export function applyReplacement < S , T extends object , K extends FunctionKeysOf < T > > ( self , target , key , newFn ) { const oldFn = Reflect . get ( target , key ) ; function replacementFn ( this , ... args ) { return newFn . call ( self , oldFn . bind ( this ) , ... args ) ; } Object . defineProperty ( target , key , { value : replacementFn , writable : true , enumerable : false , configurable : true , } ) ; } export type OverrideFunctions < S , T extends object > = { [ K in FunctionKeysOf < T > ] ? : OverrideFunction < S , T , K > ; } ; export function applyReplacements < S , T extends object > ( self , target , replacements ) { for ( const [ key , newFn ] of Object . entries ( replacements ) ) { applyReplacement ( self , target , key as any , newFn as any ) ; } }