-
Notifications
You must be signed in to change notification settings - Fork 25
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
empty attributes on ts models with target equal or above ES2022 #377
Comments
Or use class Base extends Bone {
@Column()
declare id: bigint;
}
class Note extends Base {
@Column()
declare body: string;
} |
@JimmyDaddy 又研究了一下修复方法,不考虑去掉 class fields 或者保持关闭 useDefineForClassFields 的话,用你提到的这个 declare class field 是最简单的方式 就是对 user land 入侵有点严重,model fields 得改一遍 |
重新记录一下 bug 成因,es2022 之后 class fields 的初始化行为从 set 变成了 define,也就是原本是: class Bar {
constructor(values) {
for (const name in values) this[name] = values[name];
}
} 现在变成了: class Bar {
constructor(values) {
Object.defineProperty(this, 'a', { value: values[name], ... });
}
} 并且如果类之间有继承关系,情况会更加复杂一些,例如下面这个写法:
编译后是:
在 Leoric 里面,只能在基类 Bone 里面初始化这些值,也就是上面这个示例里面的 |
动态覆盖子类的 constructor 去恢复 attribute getter/setter 也不可行 |
总结一下目前升级 target >= ES2022 可选的解决办法:
还有一个解法需要在框架层处理,就是在 egg-orm、@midwayjs/leoric 之类的组件里面,在 Model 加载阶段,主动 subclass 一下,在 subclass 的 constructor 里面恢复 attributes 对应的 property descriptor,代价是 cnpmcore 里这种直接 import 的就会 break 手动关闭 useDefineForClassFields 也有些不太可取,毕竟这个是 ES2022 之后 js 运行时的默认行为,即便 ts 可以通过编译解决,裸写 js 的项目也还是会遇到问题 增加 declare 前缀的 cons 也是同样如此 怎么选呢 |
the model above might be instantiated like an empty object when compiled with tsconfig that has
target
set to ES2022 or above:this is because public class fields will be initialized with [[Define]] rather than [[Set]] when the target is ES2022 or above. ts projects with this config will have to change the https://www.typescriptlang.org/tsconfig#useDefineForClassFields property to false.
The text was updated successfully, but these errors were encountered: