在我的应用程序中,我试图将流类型添加到Sail的水线orm。
为此,我尝试添加一个新类“ _DeferredPromise”,它是一个thenable
(或promise
,因为它正在使用promise.all并等待),但是它添加了一些额外的功能来允许链接数据库查询。 ORM上的表的典型签名是:
type DatabaseORMTy<T> = {
find: (number | {+[string]: mixed}) => _DeferredPromiseTy<$Array<T>>,
//...
}
和deferredPromise:
type _DeferredPromiseTy<T> = {
...Promise<T>,
fetch: () => _DeferredPromiseTy<T>,
limit: (string|number) => _DeferredPromiseTy<T>,
select: (?$ReadOnlyArray<string>) => _DeferredPromiseTy<T>,
skip: (number) => _DeferredPromiseTy<T>,
sort: (string) => _DeferredPromiseTy<T>,
//and more
}
问题是:我似乎无法让流程像那些延迟的诺言是诺言那样起作用,只是增加了一些附加功能。我尝试用$Exact<Promise>
添加Promise签名-这使流程抱怨您无法做出确切的Promise。我尝试使用= Promise & {...}
将其添加,并且在上面尝试过。
但是这些都显示使用错误:
const data:T = await myTable.find(1).limit(1); //would find the entry with id=1, and at most 1 entry.
显示以下错误:
Error: Cannot call await with `find(...)` bound to `p` because `_DeferredPromiseTy` [1] is incompatible with `Promise` [2].
如何使自定义类型与Promise
兼容?
[例如,在尝试Flow中(我注意到那里的错误消息有所不同):fiddle
Flow为Promise
提供了特殊处理,并且当前不允许您将await
与自定义的Thenable一起使用。但是,您可以扩展Promise
,并且Flow允许您将子类的实例用作Promise
。
您有几个选择:
您可以使用declare class
,这使Flow认为存在该类型的类。缺点是Flow允许您执行x instanceof _DeferredPromiseTy
之类的操作,或尝试构造它,即使实际上实际上没有任何此类。
declare class _DeferredPromiseTy<T> extends Promise<T> {
fetch: () => _DeferredPromiseTy<T>,
limit: (string|number) => _DeferredPromiseTy<T>,
select: (?$ReadOnlyArray<string>) => _DeferredPromiseTy<T>,
skip: (number) => _DeferredPromiseTy<T>,
sort: (string) => _DeferredPromiseTy<T>,
//and more
};
([playground)
要解决该问题,您实际上可以定义这样的类。不利之处在于,如果您只是尝试将类型添加到现有代码库中,则可能无法以实用的方式进行结构化:
class _DeferredPromiseTy<T> extends Promise<T> {
fetch(): _DeferredPromiseTy<T> { return this; }
limit(x: string|number): _DeferredPromiseTy<T> { return this; }
//and more
};
([playground)