【问题标题】:How to type annotate the constructor of "this" in Javascript with FlowType如何使用FlowType在Javascript中键入注释“this”的构造函数
【发布时间】:2017-06-26 18:48:07
【问题描述】:

我遇到了 Javascript 和 FlowType 的问题。我要做的是返回静态类,以便我可以使用this.cls.staticProperty 之类的代码轻松引用实例方法中的类方法。举个例子:

// @flow
class A {

    // This is where it fails... It cannot return Class<this>
    // ERROR: Flow: `this` type. invariant position (expected `this` to occur only covariantly)
    get cls(): Class<this> {
        return this.constructor
    }
}

现在,我知道我可以通过明确指定 A 来简单地解决这个问题,但是我在子类中遇到了问题

// @flow
class A {

    // This works
    get cls(): Class<A> {
        return this.constructor
    }
}

class B extends A {

    static myProp: string

    doSomething(): void {

        // But, now, this doesn't work
        // ERROR: Flow: property `myProp`. Property not found in statics of A 
        this.cls.myProp = "Hello World"
    }
}

我现在可以通过在 B 上指定 cls 方法来解决这个问题,就像这样:

// @flow
class A {

    // This works
    get cls(): Class<A> {
        return this.constructor
    }
}

class B extends A {

    static myProp: string

    // I have to define this again for class B
    get cls(): Class<B> {
        return this.constructor
    }

    doSomething(): void {

        // Works now, but now I'm violating the DRY principle
        this.cls.myProp = "Hello World"
    }
}

或者,我可以简单地返回Class&lt;any&gt;,如下所示:

// @flow
class A {

    // Now, we are returning the constructor of any
    get cls(): Class<any> {
        return this.constructor
    }
}

class B extends A {

    static myProp: string

    doSomething(): void {

        // Works now, but now my IDE doesn't give me auto complete
        // And I'm having to manually look up static properties and methods
        this.cls.myProp = "Hello World"
    }
}

但是,现在我的 IDE 没有给我任何类型提示或类的自动完成属性,所以我不得不从内存中输入属性和方法,这很容易出错,更不用说需要多少时间了不断查找静态方法和属性

我尝试的另一个解决方案是去掉cls getter,而是在我需要静态属性时指定实际的类名,但那里也有问题......考虑这段代码:

// @flow
class A {

    static myProp: string

    get staticMyProp(): string {
       return A.myProp
    }
}
A.myProp = "A Hello World"

class B extends A {

}
B.myProp = "B Hello World"

let bObj = new B()
console.log(bObj.staticMyProp) // Logs "A Hello World"
// But we expected "B Hello World" since we are running it from the B instance

最后一个选项....我可以每次都指定this.constructor....但我真的不想这样做...我宁愿使用this.cls,因为我就是这样' m 习惯(来自 Python 背景)

 // @flow
class A {

    static myProp: string

    get staticMyProp(): string {
       return this.constructor.myProp
    }
}
A.myProp = "A Hello World"

class B extends A {

}
B.myProp = "B Hello World"

let bObj = new B()
console.log(bObj.staticMyProp) // Logs "B Hello World" as expected

我真的希望能够使用流类型使get cls(): Class&lt;this&gt;(上面的第一个示例)选项起作用,有什么建议吗?还是我运气不好?

【问题讨论】:

    标签: javascript ecmascript-6 flowtype


    【解决方案1】:

    如果您不想违反 DRY,请不要使用典型的继承层次结构来解决常见问题。它只会导致痛苦和心痛以及非常混乱的重构。在 JavaScript / TypeScript 中,这比在其他“OO”语言中要正确 4000%。

    也就是说,可能有一些方法可以通过 F 有界多态性来说服 Flow 让你通过,但它真的不会喜欢这样。不管你怎么写,Flow(或其他声音类型系统)都会抱怨你写的。

    【讨论】:

    • 感谢您的反馈……您说的完全正确。原型继承是完全不同的,它迫使我们重新思考我们的整个生活...... =) 普通的 javascript 工作正常......只是抱怨的类型检查。你是对的,当你这样做的时候,Typescript 也会抱怨。
    • @RayPerea Bob 叔叔甚至会建议你不应该在任何地方这样做,包括 Java,因为它会导致非常脆弱的代码,当你不可避免地不得不改变时更改。很难通过这样一个小例子来提供如何保持代码 DRY 的具体示例,但是还有其他更灵活的代码重用形式,它们使您不必再考虑这些事情。另外,如果你没有读过 Clean Code,我强烈推荐它,即使你必须从 Java 翻译成 JS (flow/TS)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-04-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-19
    • 1970-01-01
    相关资源
    最近更新 更多