流字符串与字符串文字不兼容?

时间:2018-01-31 04:07:44

标签: javascript flowtype

我尝试注释自定义事件发射器并将事件名称限制为特定字符串。对于这个例子,虽然我只使用一个事件名称:

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') {
  }
}

2 个答案:

答案 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