Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Unable to access private members when redefining method of class

When defining a private member using #, and then re-defining some member that uses this private member, you will find that you cannot use it anymore:

class Foo {
    #secret = "Keyboard Cat";
    
    method() {
        console.log(this.#secret);
    }
}

const target = Foo.prototype;
const key = "method";

const desc = Object.getOwnPropertyDescriptor(target, key);

const og = desc.value;

desc.value = function (...args) {
    return og.apply(target, args);
};

Object.defineProperty(target, key, desc);

new Foo().method();

Uncaught TypeError: Cannot read private member #secret from an object whose class did not declare it

Why? All I have done is wrap around the original method in this case. Note that this example is a dramatic simplification of using decorators with TypeScript. How could I get around this while still being able to redefine and "change" the method?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel


Here’s the same thing, but with a TypeScript decorator:

const Curse: MethodDecorator = (target, _, desc) => {
    const og = desc.value as Function;

    desc.value = function (...args: any[]) {
        return og.apply(target, args);
    } as any;

    return desc;
};

class Foo {
    #secret = "Keyboard Cat";
    
    @Curse
    method() {
        console.log(this.#secret);
    }
}

new Foo().method();

Playground

>Solution :

The mistake you made is to apply the method to the target, which is Foo.prototype, not to the new Foo instance via the this keyword:

class Foo {
    #secret = "Keyboard Cat";
    
    method() {
        console.log(this.#secret);
    }
}

const target = Foo.prototype;
const key = "method";

const desc = Object.getOwnPropertyDescriptor(target, key);

const orig = desc.value;

desc.value = function (...args) {
    return orig.apply(this, args);
//                    ^^^^
};

Object.defineProperty(target, key, desc);

new Foo().method();

Foo.prototype does not have the #secret private field. You’ll get the same error with

class Foo {
    #secret = "Keyboard Cat";
    
    method() {
        console.log(this.#secret);
    }
}

Foo.prototype.method();
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading