mobx: `[MobX] Cannot decorate undefined property` when using `makeObservable` with `babel-preset-typescript`
Hi,
I am trying to upgrade to Mobx@6. This is my before and after class:
// Before
class Person {
@observable age!: number;
}
// After
class Person {
age!: number; // EDITED: forgot to add this in the original example
constructor() {
makeObservable(this, {
age: observable
});
}
}
When I run the app, the age is not yet initialized, and the error [MobX] Cannot decorate undefined property: 'age' is thrown.
I understand what it means here: based on the doc for makeObservable, only existing property will be made observable. Also I understand that this could be bad typescript usage since I use !: but this is somewhat necessary for our use-case (though I believe we could think of some workaround for this), but more importantly, this used to work fine in mobx@5 so I wonder if this is an expected breaking change in mobx@6?
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Comments: 16 (8 by maintainers)
Just an update, this problem has been resolved in
babel@7.12.0. Everything should work as expected if we follow the migration guide and turning on the flowallowDeclareFieldsfor@babel/preset-typescript@mweststrate I think I found the root cause. What happened is very nuanced.
will be treated conceptually the same as
declare age: numberby@babel/plugin-transform-typescript. So the behavior is to strip this field from class. So when I print out the object before callingmakeObservable, I don’t even see the field.But if I do:
When I print out the object before calling
makeObservable, I see the field with valueundefinedwithin the object.Now on niche thing they did was avoiding stripping the field if it was decorated so in that sense, if I do:
This should work fine, though I would love to get rid of decorators. Now my question is what should I do here:
babel? - not sure neither since I don’t have much deep knowledge on this topic and their discussion seems to be going in the direction of stripping the field with definite assignment operator@observableas a workaround until I convert fully to use some kind of factory pattern and only callmakeObservablewhen I know the field has been initialized (I can do this, though it requires some amount of refactoring to be done in my project though).Sorry if the questions seem a bit scattered, I would come back tomorrow to prune them, but I thought I should give you an update to save time.
@mweststrate Sorry I did not search properly 😦 I read through point 5 and went on to search up that flag in Typescript doc and thought that was a niche TS feature that we didn’t have to care about at all 😃. Now it all makes sense. Thank you so so much!
Yes: https://mobx.js.org/migrating-from-4-or-5.html#getting-started bullet 4 / 5. For background, see https://github.com/mobxjs/mobx/issues?q=Cannot+decorate+undefined+property first couple of hits. So you will need to declare your field explicitly in any case (without TS will complain), and if you don’t change your build config, you will have to initialise it as well.