Watermelondb: Error: Cannot use 'in' operator to search for 'initializer' in undefined (Model field decorators can only be used for simple properties)

Created on 5 Nov 2018  路  18Comments  路  Source: Nozbe/WatermelonDB

Hi,
I was using WatermelonDB for react-native, and trying to setup the same for web. For the same model, schema definition, I am hitting this case
https://github.com/Nozbe/WatermelonDB/blob/master/src/decorators/common.js#L21
Model field decorators can only be used for simple properties - method, setter or getter

This is the field definition

...
  @field('text')
  // @ts-ignore
  text;
...

which is not changed from native, and looks similar to other fields. But, I didn't follow changes to the package for a month and uses latest release now.

Also, instead of above error message, it throws error because descriptor is undefined.

TypeError: Cannot use 'in' operator to search for 'initializer' in undefined
ensureDecoratorUsedProperly
node_modules/@nozbe/watermelondb/decorators/common.js:21
  18 | 
  19 | function ensureDecoratorUsedProperly(columnName, target, key, descriptor) {
  20 |   (0, _invariant.default)(columnName, "Pass column name (raw field name) to the decorator - error in ".concat(target.constructor.name, ".prototype.").concat(key, " given."));
> 21 |   (0, _invariant.default)('initializer' in descriptor, "Model field decorators can only be used for simple properties - method, setter or getter ".concat(target.constructor.name, ".prototype.").concat(key, " given."));
  22 |   (0, _invariant.default)(!(0, _is.default)(Function, descriptor.initializer), "Model field decorators must not be used on properties with a default value - error in \"".concat(target.constructor.name, ".prototype.").concat(key, "\"."));
  23 | }
View compiled

thank you.

All 18 comments

I take it back saying the schema, model definition is not changed. I keep them as a shared local repo to share between web and native, and using the package using yarn link. so using the compiled code now. so, I assume I might be using the transpiled code now, and it is.

    __decorate([
        decorators_1.field('text')
    ], Message.prototype, "text", void 0);

I import the shared lib as

import { dbSchema } from 'xyz-shared/lib/models/schema';
import createDatabase from 'xyz-shared/lib/models/db';

const adapter = new LokiJSAdapter({
  dbName: 'xyz',
  schema: dbSchema
});

...

const database = createDatabase(adapter)
....

is that ok. Or how can I achieve a common schema/model and import as a npm package?

I am not sure how to avoid the usage of decorator and define the fields directly :-(

@radex could you please give me some pointers as I am stuck at this. Any help is appreciated.

sorry about this! will investigate tomorrow

@bsr203 hey, can you show me your babel configuration? Looks like your decorator is misapplied.

PS. You could contribute an improvement to the error message, since I have 'initializer' in descriptor and there should first be an invariant(descriptor,decorator not applied to a property`)

@radex Thanks for getting back to me. this is my babelrc

shared

{
  "presets": [
    "@babel/preset-react",
    "@babel/preset-typescript",
    "@babel/preset-env"
  ],
  "plugins": [
    [
      "@babel/plugin-proposal-decorators",
      {
        "legacy": true
      }
    ],
    ["@babel/plugin-proposal-class-properties", { "loose": true }],
    [
      "@babel/plugin-transform-runtime",
      {
        "helpers": true,
        "regenerator": true
      }
    ]
  ]
}

web

{
  "presets": [["react-app", { "flow": false, "typescript": true }]],
  "plugins": [
    [
      "@babel/plugin-proposal-decorators",
      {
        "legacy": true
      }
    ],
    ["@babel/plugin-proposal-class-properties", { "loose": true }],
    [
      "@babel/plugin-transform-runtime",
      {
        "helpers": true,
        "regenerator": true
      }
    ]
  ]
}

watermelonissue.zip

Hi @radex
please see the attached file, which has 2 folders

  1. shared : shared model, which is compiled to es5/ commonjs.
  2. web : a CRA app, ejected to add watermelonDB config.

to reproduce:
on shared:

yarn install
yarn build (the transpiled code is in lib)
yarn link

on web

yarn install
yarn link "shared"
yarn start

please let me know if you need any clarification.

greatly appreciate your time on this.
bsr.

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

I know this has been closed, but has anyone figured out a workaround for this issue?

I get the error Cannot use 'in' operator to search for 'initializer' in undefined when the @field decorator is used because descriptor is undefined.

I'm using React-native with TypeScript

@davideweaver any luck solving this issue?

This is happening during our Jest test run using ts-jest.

TypeError: Cannot use 'in' operator to search for 'initializer' in undefined
  at ensureDecoratorUsedProperly (node_modules/@nozbe/watermelondb/decorators/common.js:17:41)
  at node_modules/@nozbe/watermelondb/decorators/field/index.js:25:45
  at Object.__decorate (node_modules/tslib/tslib.js:90:114)
  at Object.<anonymous> (packages/main/services/transactions/models/Transaction.model.ts:213:9)
  at Object.<anonymous> (packages/main/services/transactions/models/index.ts:6:53)

I found out this is happening because the code generated by TypeScript for decorators doesn鈥檛 work with the decorator code generated by this project. TypeScript doesn鈥檛 pass property descriptors when the decorator is instantiated. I think TypeScript generates older-style decorator code.

@radex, could you reopen this issue? It's still an issue in the latest version of WatermelonDB. I successfully moved from Realm to WatermelonDB(and I really love it!), only the tests are failing now because of this issue.

Sure! Maybe we need to tweak Babel config for Watermelon? Or maybe it's better for TypeScript projects to use 馃崏 source code (with babel config to transpile in the project)?

Did anybody of you found already a fix for this issue? I've struggled with this issue for one hour now but I couldn't solve it :-(

Not the ideal solution, but I use patch-package to patch the watermelon-db package after install. I comment out the checks in /node_modules/@nozbe/watermelondb/decorators/common.js. I don't know how to resolve the differences between TypeScript and the code generated in this package.

@davideweaver and decorators still work this way?

@radex I can't be 100% sure, but it doesn't look like any decorators you are using actually utilize the descriptor argument passed to them. TypeScript doesn't pass descriptor in the code it generates for setting up decorators.

correction
@lazy does not work because it depends on descriptor

Great! In that case this should be as simple as changing the invariant to only check for initializer if descriptor is present. Can uou send a quick PR?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

markorusic picture markorusic  路  4Comments

ieschalier picture ieschalier  路  8Comments

roots-ai picture roots-ai  路  4Comments

arambrosius picture arambrosius  路  8Comments

mjstelly picture mjstelly  路  7Comments