TypeScriptでabstract classのgetterがundefinedになってしまう現象について
https://gyazo.com/4d2febe94b38608da39ba6d066117dde
クラスの定義はこう
code:class.ts
export abstract class BaseClass {
id: number
abstract ref: firebase.firestore.DocumentReference
...
}
export class ExtendClass extends BaseClass {
get ref() {
return firestore.collection("hogehoge").doc(this.id)
}
}
この場合、ExtendClassにおいてrefがundefinedに上書きされてしまう場合がある。
しかし、どうやらこれはTypeScript・ESの想定挙動らしい。
どういうこと?
結局これはバグではなく、想定挙動に近づけたということらしい。
TS3.7.2からuseDefineForClassFieldsというオプションが追加され、constructorで明示的に割り当てられていないクラス変数は、void 0(undefined)を代入するべきというES本来の仕様に従った形(?)になった。
これはbabel-preset-typescriptにも取り入れられ?(delcareのサポートだから異なる?どっちが先?)オプションにallowDeclareFieldsが追加されたらしい
とりあえず現在の環境はnextなので、tsconfigにuseDefineForClassFieldsを設定してみたが、相変わらずundefinedのままになってしまう。
code:.babelrc
{
"presets": [
[
"next/babel",
{
"preset-typescript": {
"allowDeclareFields": true
}
}
]
],
"plugins": []
}
だめだった。
issueにあったplaygroundのコードに倣いdeclareを置いてみるも、babel側の変換プラグインが必要と言われて通らない。 code:declare.ts
export abstract class BaseClass {
id: number
declare abstract ref: firebase.firestore.DocumentReference
...
}
https://gyazo.com/e99b740d7a1406532aadf91cba11c0c4
その後、babelの設定を書き換えてみるも、うまく動かなかった。
Workaround
とりあえずコンストラクタで初期化に参照を作るか、代入初期化を解除してしまえばよさそうなので、こうした。
code:class.ts
export abstract class BaseClass {
abstract ref: firebase.firestore.DocumentReference
...
constructor () {
// @ts-ignore
delete this.ref
}
}
明らかに最悪なので、もっと良いやり方があれば教えてほしい
というかnextにおけるこういった場合の正しいbabelrcの指定を教えてほしい
https://gyazo.com/10acfa0baf55e570f6ea0e38cc1fd8c3
申し訳程度のメモ書きがなされている図