Mobx: [v6] Cannot decorate ... the property is already decorated as observable

Created on 22 Sep 2020  路  6Comments  路  Source: mobxjs/mobx

Using mobx 6.0.0-rx8 with the following decorator-based code will throw this exception:
[MobX] Cannot decorate 'value1': the property is already decorated as observable

class BaseClass {

    @observable
    value1?: number;

    constructor() {
        makeObservable(this);
    }

}

class SubClass extends BaseClass {

    constructor() {
        super();
        makeObservable(this);
    }

    @computed
    get value1Computed() {
        return this.value1;
    }

}

new SubClass();

After debugging the code I found out that it is related to this code

                    if (!hasProp(target, key) && !hasProp(current, key)) {
                        // not all fields are defined yet, so we are in the makeObservable call of some super class,
                        // short circuit, here, we will do this again in a later makeObservable call
                        return true
                    }

This check fails, if the subclass only contains computed properties and no single observable variable.

Modifying SubClass by adding a simple observable value indeed removed the exception:

class SubClass extends BaseClass {

    @observable
    value2?: number;

    constructor() {
        super();
        makeObservable(this);
    }

    @computed
    get value1Computed() {
        return this.value1;
    }

}

Another smaller issue I noticed is that in development bundles with webpack the minified file mobx.es.js was used which makes debugging these kinda things difficult.
I had to go into package.json and remove the module entry to get an unminified build for debugging.

Also (but this might be related to some issue in my webpack config) the source maps for the cjs build was not working properly for me.

馃悰 bug

Most helpful comment

Good catch and thanks for the analysis! Will make sure this gets fixed before the release.

All 6 comments

Good catch and thanks for the analysis! Will make sure this gets fixed before the release.

Pushed a fix, thanks for reporting!

I saw your fix and I think I still know a way to break it :D
Just wanted to write this here as a reminder for now for me as well, because I don't have time to test my guess right now (will probably do it when a new npm release is out)

@mweststrate Just want to check if this is intended behavior in v6. But I'm seeing error now for this case after upgrading from V5 to V6


abstract class Animal {}
class Dog extends Animal {}

class BaseClass {
    @observable value1: Animal;

    constructor() {
        makeObservable(this);
    }
}

class SubClass extends BaseClass {
    @observable value1: Dog;

    constructor() {
        super();
        makeObservable(this);
    }
}

I'm getting the same error Cannot decorate 'value1': the property is already decorated as observable.


As for the reason why I'm doing this, I want my child class to have the same property but of a more specific type than its superclass (just a typescript thing)


EDIT
@mweststrate I see this in the list of breaking changes "It is no longer possible to re-decorate a field (through either @observable or makeObservable) that is already declared in a super class." :(

You can just not add the @observable attribute to value1 in SubClass and it might work ... or you might have to do it the other way round ... not sure.
Otherwise you can still use a generic in the base class as an alternative.

@akphi TypeScript has special syntax for refining the type of a property without redeclaring it; use declare value1: Dog instead. Playground

Was this page helpful?
0 / 5 - 0 ratings