saa*_*adq 9 javascript eventemitter flowtype flow-typed
举个例子,假设我有一个类只有发出三种可能的事件- 'pending'或'success'或'failure'.此外,接收的参数类型eventHandler取决于发出的事件 -
'pending',eventHandler没有收到任何论据'success',eventHandler收到一个number'failure',eventHandler收到一个Error以下是我尝试建模的方法:
// @flow
import EventEmitter from 'events'
type CustomEventObj = {|
pending: void,
success: number,
error: Error
|}
declare class MyEventEmitter extends EventEmitter {
on<K: $Keys<CustomEventObj>>(
eventName: K,
eventHandler: (
e: $ElementType<CustomEventObj, K>,
...args: Array<any>
) => void
): this
}
Run Code Online (Sandbox Code Playgroud)
但是,这会导致如下错误:
Error ????????????????????????????????????????????????????????????????????????????????????????????????????? test.js:12:3
Cannot extend EventEmitter [1] with MyEventEmitter because an indexer property is missing in CustomEventObj [2] in the
first argument of property on.
[1] 3? import EventEmitter from 'events'
:
8? error: Error
9? |}
10?
11? declare class MyEventEmitter extends EventEmitter {
[2] 12? on<K: $Keys<CustomEventObj>>(
13? eventName: K,
14? eventHandler: (
15? e: $ElementType<CustomEventObj, K>,
16? ...args: Array<any>
17? ) => void
18? ): this
19? }
20?
Run Code Online (Sandbox Code Playgroud)
我不希望有一个索引器属性,CustomEventObj因为不会杀死只有3个可能事件的点?
任何帮助,将不胜感激.
嗯,我有一个好消息和一个坏消息。好消息是,您将能够让 Flow 了解什么作为参数传递给处理程序on。坏消息是,您将无法告诉 Flow 除了您想要的事件之外的其他事件是不允许的。
因为您要扩展 EventEmitter 类,所以您明确声明您的类将执行与 EventEmitter 相同的操作。因此,由于 EventEmitter 的on处理程序将接受 any string,因此您的“MyEventEmitter”也必须接受处理程序中的任何字符串on。即使您只是在收到意外字符串时抛出错误,Flow 仍然希望您遵循该约定。
现在好消息是:您可以让 Flow 知道您期望在某些事件上收到什么样的参数。诀窍是指定on处理程序的多个声明,如下所示:
// @flow
import EventEmitter from 'events'
type CustomEventObj = {|
pending: void,
success: number,
error: Error
|}
declare class MyEventEmitter extends EventEmitter {
on(
'pending',
// Alternatively, you can pass in a callback like () => void
// as the type here. Either works for the examples below.
(
e: null,
...args: Array<any>
) => void
): this;
on(
'success',
(
e: number,
...args: Array<any>
) => void
): this;
on(
'error',
(
e: Error,
...args: Array<any>
) => void
): this;
// Just to satisfy inheritance requirements, but this should
// throw at runtime.
on(
string,
(
e: mixed,
...args: Array<any>
) => void
): this;
}
let myInstance = new MyEventEmitter()
myInstance.on('pending', () => {}) // works
myInstance.on('success', (num: number) => {console.log(num * 2)}) // works
myInstance.on('success', (badStr: string) => {console.log(badStr.length)}) // Error
Run Code Online (Sandbox Code Playgroud)
现在,流程了解,例如,如果事件是“成功”,则回调应该接受一个数字(或某种包含数字的联合类型,例如 或string | number)any。
如果您希望 Flow仅允许您传入特定事件,那么您将无法从 EventEmitter 类继承。(推理是这样的:如果你将 MyEventEmitter 传递给一些传递其他事件的外部代码会怎样?Flow 将无法阻止这种情况发生,并且外部代码也没有好的方法知道它无法传入除“待处理”、“成功”或“失败”之外的事件)
我已经在 GitHub 上发布了我的代码副本,用于尝试/参考/分叉。我将其发布在https://flow.org/try/上,但我似乎无法让它理解来自 EventEmitter 或 events$EventEmitter 的继承。
警告:我认为您可以为函数指定预期参数的原因是因为 events$EventEmitter 的on函数将handler参数声明为Functiontype。这种类型有点奇怪,而且大多未经检查。on因此,虽然这种在处理程序上进行多重声明的技术目前有效(Flow 0.69.0),但它可能会因 Flow 或 events$EventsEmitter typedef 的未来版本而中断。
| 归档时间: |
|
| 查看次数: |
242 次 |
| 最近记录: |