因为myMember属性是在父构造函数中访问的(init()在调用期间被super()调用),所以无法在不遇到竞争条件的情况下在子构造函数中定义它。
有几种替代方法。
init 钩
init被视为不应在类构造函数中调用的钩子。相反,它被显式调用:
new B();
B.init();
或者它被框架隐式调用,作为应用程序生命周期的一部分。
静态属性
如果一个属性应该是一个常量,它可以是静态属性。
这是最有效的方法,因为这是静态成员的用途,但语法可能没有那么吸引人,因为this.constructor如果子类中应正确引用静态属性,则它需要使用而不是类名:
class B extends A {
    static readonly myMember = { value: 1 };
    init() {
        console.log((this.constructor as typeof B).myMember.value);
    }
}
属性 getter/setter
可以使用get/set语法在类原型上定义属性描述符。如果一个属性应该是原始常量,它可以只是一个 getter:
class B extends A {
    get myMember() {
        return 1;
    }
    init() {
        console.log(this.myMember);
    }
}
如果属性不是恒定的或原始的,它会变得更加棘手:
class B extends A {
    private _myMember?: { value: number };
    get myMember() {
        if (!('_myMember' in this)) {
            this._myMember = { value: 1 }; 
        }
        return this._myMember!;
    }
    set myMember(v) {
        this._myMember = v;
    }
    init() {
        console.log(this.myMember.value);
    }
}
就地初始化
一个属性可以在它首先被访问的地方被初始化。如果这发生在可以在类构造函数之前访问的init方法中,这应该发生在那里:thisB
class B extends A {
    private myMember?: { value: number };
    init() {
        this.myMember = { value: 1 }; 
        console.log(this.myMember.value);
    }
}
异步初始化
init方法可能会变得异步。初始化状态应该是可跟踪的,因此该类应该为此实现一些 API,例如基于 promise:
class A {
    initialization = Promise.resolve();
    constructor(){
        this.init();
    }
    init(){}
}
class B extends A {
    private myMember = {value:1};
    init(){
        this.initialization = this.initialization.then(() => {
            console.log(this.myMember.value);
        });
    }
}
const x = new B();
x.initialization.then(() => {
    // class is initialized
})
对于这种特殊情况,这种方法可能被视为反模式,因为初始化例程本质上是同步的,但它可能适用于异步初始化例程。
脱糖课
由于ES6类对使用限制this之前super,子类可以被脱到一个函数来规避这一限制:
interface B extends A {}
interface BPrivate extends B {
    myMember: { value: number };
}
interface BStatic extends A {
    new(): B;
}
const B = <BStatic><Function>function B(this: BPrivate) {
    this.myMember = { value: 1 };
    return A.call(this); 
}
B.prototype.init = function () {
    console.log(this.myMember.value);
}
这很少是一个好的选择,因为应该在 TypeScript 中额外输入脱糖类。这也不适用于本机父类(TypeScriptes6和esnext目标)。