JSFiddle - React, Tailwind, and code Playground

JavaScript

const mutualRecursion = (obj) => {
    const newObj = {};
    for (const key in obj) {
        newObj[key] = obj[key](obj);
    }
    return newObj;
}

const makeCounterBase = () => {
    let counter = 0;
    return {
        get: self => () => counter,
        set: self => value => counter = value,
        inc: self => () => self.set(self)(self.get(self)()+1)
    };
};

const makeCounter = () => {
    return mutualRecursion(makeCounterBase());
};

const makeLoggingCounter = () => {
    const base = makeCounterBase();
    return mutualRecursion({
        get: self => () => { console.log('get!'); return base.get(self)(); },
        set: self => value => { console.log('set!'); return base.set(self)(value); },
        inc: self => () => { console.log('inc!'); return base.inc(self)(); }
    });
}


const counter1 = makeCounter();

console.log('Calling get()');
console.log(counter1.get());

console.log('Calling set(2)');
counter1.set(2);

console.log('Calling get()');
console.log(counter1.get());

console.log('Calling inc()');
counter1.inc();

console.log('Calling get()');
console.log(counter1.get());


const counter2 = makeLoggingCounter();

console.log('Calling get()');
console.log(counter2.get());

console.log('Calling set(2)');
counter2.set(2);

console.log('Calling get()');
console.log(counter2.get());

console.log('Calling inc()');
counter2.inc();

console.log('Calling get()');
console.log(counter2.get());