New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[MobX] Cannot decorate undefined property
when using makeObservable
with babel-preset-typescript
#2486
Comments
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. |
@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! |
Np!
…On Mon, 5 Oct 2020, 21:34 An Phi, ***@***.***> wrote:
@mweststrate <https://github.com/mweststrate> Sorry I did not search
properly :( I read through point 5 and went on to search up that flag in
Typescript doc and though that was not a feature we care about at all :).
Now it all makes sense. Thank you so so much!
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#2486 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAN4NBHQHKKTDZ5RJZLBMCLSJIUUNANCNFSM4SFEJVHQ>
.
|
@mweststrate actually, it doesn't seem to work for my case. I have enabled the options in point 4 and 5. // tsconfig.json
{
...
"useDefineForClassFields": true
} // babel.config.js
...
plugins: [
['@babel/plugin-proposal-class-properties', { loose: false }],
] Notice the field I had use the type-guard |
probably a config / cache issue somewhere. Above should do the trick. Best create a minimal repo if it doesn't. |
@mweststrate I created a test case for this - https://github.com/akphi/config-tester Now if I have this preset running after // will have problem with Mobx
presets: [
'@babel/preset-env',
'@babel/preset-react',
'./dev/test-preset', // this now will run after `preset-typescript`
['@babel/preset-typescript', {
onlyRemoveTypeImports: true,
allowDeclareFields: true
}],
]
// no problem with [Mobx] Can't decorate ..., but will have problem with Typescript `declare` usage in classes
presets: [
'@babel/preset-env',
'@babel/preset-react',
['@babel/preset-typescript', {
onlyRemoveTypeImports: true,
allowDeclareFields: true
}],
'./dev/test-preset', // this now will run before `preset-typescript`
] However, I cannot do this since due to my usage of UPDATED: may relate to this, although our problem is slightly different is that the field is picked up, but it's not initialized. Not too proficient with babel/typescript transpiling debugging myself, but I will try. |
@mweststrate I think I found the root cause. What happened is very nuanced. age!: number; will be treated conceptually the same as But if I do: age: number; // typescript will complain because I don't initialize this, but this will still compile fine When I print out the object before calling Now on niche thing they did was avoiding stripping the field if it was decorated so in that sense, if I do: @observable age!: number; This should work fine, though I would love to get rid of decorators. Now my question is what should I do here:
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. |
Interesting, yes this sounds like an issue in babel; Just to reiterate for future readers: A work around should be to assign a value to the |
[MobX] Cannot decorate undefined property
when using makeObservable
[MobX] Cannot decorate undefined property
when using makeObservable
with babel-preset-typescript
@mweststrate possibly, but for the case you just sent, it works because you run |
yep, that makes sense. I filed an issue over at babel project. Honestly, my use case may not be that popular Besides what you said, I think another workaround for folks who still have decorator support on is to do this: class Person {
@observable age!: number;
constructor() {
makeObservable(this, {
age: observable
});
}
} @mweststrate Should we close this? |
Yes, can be closed for now. Thanks for filing that issue! |
Just an update, this problem has been resolved in |
@akphi thanks for the update! |
I've had this exact issue as well and it took me way longer than it should to figure it out. In general, just after class constructor has finished, all properties of the class were becoming undefined. Example of such class was class Foo {
@prop()
bar!: string;
} I wanted to see what exactly is removing those props as if I was adding So I've disabled sourcemaps in chrome and turned out babel is adding something like this just after the constructor: Object(_Users_project_node_modules_babel_runtime_helpers_esm_initializerDefineProperty__WEBPACK_IMPORTED_MODULE_0__["default"])(_this, "email", _descriptor, Object(_Users_project_node_modules_babel_runtime_helpers_esm_assertThisInitialized__WEBPACK_IMPORTED_MODULE_2__["default"])(_this)); the same snippet is added for each prop resulting in them becoming undefined. How I solved it was 'delaying' initialization code to happen just after the constructor. so instead of class Foo {
constructor() {
this.init();
}
init() {}
} I do
This way I bypass it and my init code is called after those props are stripped. I belive this is a bug in babel, as class properties initialization injected by babel should probably check if those props are already initialized by something else during constructor call. |
Hi,
I am trying to upgrade to Mobx@6. This is my before and after class:
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 inmobx@5
so I wonder if this is an expected breaking change inmobx@6
?The text was updated successfully, but these errors were encountered: