考虑以下类型:
declare class Test<T> {
static of(value: T): Test<T>;
map<U>(fn: (value:T) => U): Test<U>;
}
现在,对于功能ap
,T
是function
,它的工作方式如下:
Test.of(x => x * 2)
.ap(Test.of(5))
.map(console.log) // Output(number): 10
Test.of(x => `${x * 2}!`)
.ap(Test.of(5))
.map(console.log) // Output(string): 10!
因此,要正确键入支票ap
,我需要执行ap(Test<[get type of x]>): [type of output of T]
我尝试了Test<I, O>
,其中I
对于值是可选的。但是,它为其他功能增加了许多不必要的东西。有没有更好的方法来解决这个问题?
注意:我正在尝试为data.task
编写类型定义答案 0 :(得分:2)
这是一个棘手的问题!对于所有ap()
,Test<T>
的{{1}}实例不能调用T
方法,但仅当T
是一个最多只能获得一个参数的函数时。{ / p>
所以你真正需要的东西仍然是TODO for Flow。它看起来像这样:
declare class Test<T> {
static of(value: T): Test<T>;
map<U>(fn: (value:T) => U): Test<U>;
ap<I,O>(this: Test<(in: I) => O>, test: Test<I>): Test<O>;
}
它声明this
必须是Test<T>
,T
是一个I
的函数。 Here's a GitHub issue about it
与此同时,您可以进行一阶近似。它看起来像这样:
declare class Test<T> {
static of<I, O>(fn: (in: I) => O): FuncTest<I, O>;
static of(value: T): Test<T>;
map<U>(fn: (value:T) => U): Test<U>;
}
declare class FuncTest<I, O> extends Test<(in: I) => O> {
ap(x: Test<I>): Test<O>;
}
Test.of(x => x * 2)
.ap(Test.of(5))
.map(x => (x: number)) // no error
Test.of(x => `${x * 2}!`)
.ap(Test.of(5))
.map(x => (x: string)) // no error
Try this example on flowtype.org/try
这种方法的缺点是ap()
返回Test<O>
,即使O
是函数。所以你不能两次打电话给ap()
。
Test.of(x => Test.of(y => x * y))
.ap(Test.of(5))
.map(x => (x: Test<(y: number) => number>)); // This is fine
Test.of(x => Test.of(y => x * y))
.ap(Test.of(5))
.ap(Test.of(2)) // This is an error :(