Strange Typescript编译错误:'this'无法在当前位置引用,有人可以解释一下吗?

时间:2013-12-31 12:17:37

标签: typescript

我认为这是有充分理由的,但对我来说似乎很奇怪。请将以下代码作为问题的示例。

class Foo {
    constructor(referenceMethod: () => void) {
    }
}

class Bar extends Foo {

    TestProperty: string = "boo";

    constructor() {
        super(this.ReferenceMethod);
    }

    ReferenceMethod() {

    }
}

这会产生编译器错误

  

'this'无法在当前位置引用。

如果我们初始化构造函数中的TestProperty,编译器很高兴并且世界按预期旋转,当然如果我们不将referenceMethod的引用传递给超级调用,我们可以在外面设置TestProperty构造函数很好。

然而,我只是不明白为什么一起做这两件事会导致问题。如果有人能够对此有所了解,那将有助于我的理解。

3 个答案:

答案 0 :(得分:5)

Typescript language specification中的8.3.2:

  

构造函数体中的第一个语句必须是超级调用   如果以下两个都是真的:      1.包含类是派生类      2.构造函数声明参数属性或包含类声明         具有初始化程序的实例成员变量。

示例中的包含类声明了一个名为TestProperty的变量,该变量使用初始值设定项:

 TestProperty: string = "boo";

您看到错误的原因是编译器要求constructor的第一行是super的调用,给定您班级的当前布局(#2来自上面的语言规范)。因此,这意味着当您开始引用类的属性(例如TestProperty)时,类未完全初始化。虽然ReferenceMethod将被初始化并且可用,但成员变量仍然不会,这可能会破坏您班级中的其他功能。

虽然语言作者可以生成可以避免此问题的工作代码,但当它以您找到的方式工作时,它显然更容易且更一致。

作为替代方案,您可以尝试添加一个initialize方法,该方法在构造函数完全初始化类后执行相同的逻辑。这无疑是第二步,但它适用于TypeScript。但是,请小心确保在构造函数初始化成员变量后>初始化为

答案 1 :(得分:0)

似乎FooBar有不同的行为。 Foo接受回调作为其构造函数,但Bar将回调作为实例方法。你的真实用例是什么?也许Bar应该撰写(包含)Foo而不是扩展它。

或者,您可以修改Foo的行为以接受可选回调,还可以定义用作默认值的可覆盖实例方法。然后派生类可以忽略回调参数,而只是覆盖实例方法。

选项1:作文

class Foo {
    constructor(referenceMethod: () => void) {
    }
}

class Bar {

    TestProperty: string = "boo";
    foo: Foo;

    constructor() {
        this.foo = new Foo(this.ReferenceMethod);
    }

    ReferenceMethod() {

    }
}

选项2:参考方法为可选的arg和可覆盖的

class Foo {
    constructor(referenceMethod?: () => void) {
        if (referenceMethod) {
            this.ReferenceMethod = referenceMethod;
        }
    }

    ReferenceMethod():void {}
}

class Bar {

    TestProperty: string = "boo";

    constructor() {
    }

    ReferenceMethod():void {

    }
}

答案 2 :(得分:0)

如果某人处理此错误,在构造函数中使用oci.dllprivate修饰符时也会发生这种情况。

尝试:

public

而不是:

constructor(x : number) {
    ... super call with this reference
    this.x = x;
}

private x : number;