如何处理值和函数的多态类型?
How to handle polymorphic type for both value and function?
考虑以下类型:
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
编写类型定义
这是一个棘手的问题!不能对所有 T
的 Test<T>
的实例调用 ap()
方法,但仅当 T
是一个最多接受一个参数的函数时。
所以你真正需要的是 Flow 的 TODO。它看起来像这样:
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()
returns 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 :(
考虑以下类型:
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
编写类型定义这是一个棘手的问题!不能对所有 T
的 Test<T>
的实例调用 ap()
方法,但仅当 T
是一个最多接受一个参数的函数时。
所以你真正需要的是 Flow 的 TODO。它看起来像这样:
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()
returns 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 :(