Method decorator should return first execution result Typescript

I have a method decorator that allows to execute a decorated method only once.This function works good,but at my third unit test it failes because it gives undefined but should return first execution result.
This is my decorator:

import "reflect-metadata";

const metadataKey = Symbol("initialized");

function once(
    target: any,
    propertyKey: string,
    descriptor: PropertyDescriptor
) {
    const method = descriptor.value;
    descriptor.value = function (...args) {
        const initialized = Reflect.getMetadata(
            metadataKey,
            target,
            propertyKey
        );

        if (initialized) {
            return;
        }

        Reflect.defineMetadata(metadataKey, true, target, propertyKey);

        method.apply(this, args);
    };
}  

I think the problem is in the return from the if statement,it should return something but idk what.I played a little but got no succes,thats why i beg you for help.
These are the unit tests:

describe('once', () => {
    it('should call method once with single argument', () => {
        class Test {
            data: string;
            @once
            setData(newData: string) {
                this.data = newData;
            }
        }
        const test = new Test();
        test.setData('first string');
        test.setData('second string');
        assert.strictEqual(test.data, 'first string')
    });

    it('should call method once with multiple arguments', () => {
        class Test {
            user: {name: string, age: number};
            @once
            setUser(name: string, age: number) {
                this.user = {name, age};
            }
        }
        const test = new Test();
        test.setUser('John',22);
        test.setUser('Bill',34);
        assert.deepStrictEqual(test.user, {name: 'John', age: 22})
    });

    it('should return always return first execution result', () => {
        class Test {
            @once
            sayHello(name: string) {
                return `Hello ${name}!`;
            }
        }
        const test = new Test();
        test.sayHello('John');
        test.sayHello('Mark');
        assert.strictEqual(test.sayHello('new name'), 'Hello John!')
    })
}); 

Thanks in advance!


Solution 1:

This decorator basically does memoization, but the result of the method call isn't stored anywhere. This is what's missing.

My suggestion would be to add another piece of metadata called result or something:

const meta = Reflect.getMetadata(...);

if (meta?.initialized) return meta.result;

const result = method.apply(this, args);
const newMeta = { initialized: true, result };

Reflect.defineMetadata(metadataKey, newMeta, target, propertyKey);