-
-
Notifications
You must be signed in to change notification settings - Fork 610
Description
Describe the bug
I try to define an entity with a SerializedPrimaryKey property. The id getter/setter can be correctly defined when using ts-jest. However, transpiling the code with babel in production build (I am using nestjs), the id getter/setter fails to be defined.
For example:
@Entity()
class MyEntity {
@PrimaryKey()
_id!: ObjectId;
@SerializedPrimaryKey()
id!: string;
}
// some where in my code
const myEntity = new MyEntity();
wrap(myEntity).assign({ _id: new ObjectId() }, { em })
console.log(myEntity.id) // output string id in test but undefined in productionLater, after looking into the source code, I found that EntityHelper define the id property to the entity prototype. However, with above definition, the transpiled MyEntity class constructor would define id property with descriptor { value: undefined, writable: true, enumerable: true, configurable: true}. As a result, the entity instance will never reference to its prototype for its id property.
Workaround
I figured out two workarounds.
The first way is to use Object.create instead of constructor. The limitation is that property initializers would not be called.
@Entity()
class MyEntity {
@PrimaryKey()
_id!: ObjectId;
@SerializedPrimaryKey()
id!: string;
}
// some where in my code
const myEntity = Object.create(MyEntity.prototype);
wrap(myEntity).assign({ _id: new ObjectId() }, { em })
console.log(myEntity.id) // output string id in both test and productionThe second way is to define id as a dummy getter as it would be overwrite by EntityHelper anyway. The dummy getter is not looking good.
@Entity()
class MyEntity {
@PrimaryKey()
_id!: ObjectId;
@SerializedPrimaryKey()
get id(): string { return '' };
}
// some where in my code
const myEntity = new MyEntity();
wrap(myEntity).assign({ _id: new ObjectId() }, { em })
console.log(myEntity.id) // output string id in both test and productionTo Reproduce
Here is my babel.config.json:
{
"presets": [
[
"@babel/env",
{
"targets": {
"browsers": "> 0.5%, last 2 versions, Firefox ESR, not dead"
},
"useBuiltIns": "usage",
"corejs": { "version": 3, "proposals": true }
}
],
"@babel/preset-react",
"@babel/preset-typescript"
],
"plugins": [
"babel-plugin-transform-typescript-metadata",
["@babel/plugin-proposal-decorators", { "legacy": true }],
["@babel/plugin-proposal-class-properties", { "loose": true }]
]
}Afterthought
It seems that mutating class prototype may cause some inconsistent behaviors between untranspiled and transpiled code. Is there a better way to achieve this? Babel complies the ES6 spec and typescript may change in future. Thus, I think this issue should be addressed.
Thanks for the great work.
Versions
| Dependency | Version |
|---|---|
| node | 12.8.0 |
| typescript | 4.0.2 |
| @mikro-orm/core | 4.0.0 |
| @mikro-orm/mongodb | 4.0.0 |
| @babel/cli | 7.10.5 |
| @babel/core | 7.11.4 |
| @babel/plugin-proposal-class-properties | 7.10.4 |
| @babel/plugin-proposal-decorators | 7.10.5 |
| @babel/preset-env | 7.11.0 |
| @babel/preset-react | 7.10.4 |
| @babel/preset-typescript | 7.10.4 |