我尝试注释自定义事件发射器并将事件名称限制为特定字符串。对于这个例子,虽然我只使用一个事件名称:
class MyEmitter extends EventEmitter {
on(event: 'foo', listener: Function): this {
return super.on(event, listener);
}
}
Flow并不喜欢这样,并抱怨'foo'
与string
不兼容?
24: class MyEmitter extends EventEmitter {
^^^^^^^^^^^^ MyEmitter. Cannot extend
24: class MyEmitter extends EventEmitter {
^^^^^^^^^^^^ EventEmitter
Property `on` is incompatible:
v-------------------------------------------
25: on(event: 'foo', listener: Function): this {
26: return super.on(event, listener);
27: }
^ function. This type is incompatible with
660: on(event: string, listener: Function): this;
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function type. See lib: /private/tmp/flow/flowlib_15c48d81/node.js:660
The first parameter is incompatible:
25: on(event: 'foo', listener: Function): this {
^^^^^ string literal `foo`. Expected string literal `foo`
660: on(event: string, listener: Function): this;
^^^^^^ string. See lib: /private/tmp/flow/flowlib_15c48d81/node.js:660
[编辑]
tryflow上的独立示例:
class Foo {
on(foo: string) {
}
}
class Bar extends Foo {
on(foo: 'bar') {
}
}
答案 0 :(得分:1)
由于Bar
的{{1}}函数覆盖on
s,子类方法中Foo
的类型需要是超类中相应类型的子类型方法。虽然foo
是'bar'
,但所有string
都不是string
。
例如,这些将编译正常:
'bar'
不幸的是,因为它具有逆变输入,所以你在Flow中寻找的是不可能的。文档的效果为example。我想解决方法是使用一个简单调用重载版本的包装函数,因为这里不能使用泛型。
虽然不相关,但有趣的是,对协变输入(您正在寻找的)的支持并不常见。 Wikipedia says艾菲尔是支持它的独特“主流”语言。
答案 1 :(得分:0)
您可以使用限制创建一个界面:
class Foo {
on(foo: string) {
}
}
interface IBar {
on(foo: 'bar'): void;
}
class Bar extends Foo implements IBar {
on(foo: string) {
}
}
const bar: IBar = new Bar();
bar.on('bar'); //OK
bar.on('foo'); //Error