/** Decorator for memoizing the result of a method or get accessor. */ export function Memoize ( target , propertyName , descriptor ) { if ( descriptor . value != null ) descriptor . value = getNewFunction ( descriptor . value ) ; else if ( descriptor . get != null ) descriptor . get = getNewFunction ( descriptor . get ) ; else throw new Error ( "Only put a Memoize decorator on a method or get accessor." ) ; } const weakMap = new WeakMap < object , Map < string , unknown > > ( ) ; let counter = 0 ; function getNewFunction ( originalFunction ) { const identifier = counter ++ ; function decorator ( this , ... args ) { let propertyValues = weakMap . get ( this ) ; if ( propertyValues == null ) { propertyValues = new Map < string , unknown > ( ) ; weakMap . set ( this , propertyValues ) ; } let propName = `__memoized_value_${ identifier }` ; if ( arguments . length > 0 ) propName += "_" + JSON . stringify ( args ) ; let returnedValue ; if ( propertyValues . has ( propName ) ) returnedValue = propertyValues . get ( propName ) ; else { returnedValue = originalFunction . apply ( this , args ) ; propertyValues . set ( propName , returnedValue ) ; } return returnedValue ; } return decorator ; }