我从Ramda借用了tail
函数的声明:
declare function tail<T,V:Array<T> | string>(xs: V): V;
我的类型Query
基本上是ReaderT Promise
monad:
// @flow
class Query<C, T> {
run: (config: C) => Promise<T>;
constructor(runner : (config: C) => Promise<T>) {
this.run = runner
}
bind <U>(f : ((a: T) => Query<C, U>) ) : Query<C, U> {
return new Query(config => this.run(config).then(x => f(x).run(config)))
}
map <U>(f : (a: T) => U) : Query<C, U> {
return new Query(config => this.run(config).then(f))
}
}
使用此定义Flow无法键入以检查此表达式:
new Query(config => Promise.resolve(config + 1)) // config is {init: number}
.run({init: 2}).then(console.log)
但是当我使用声明的sequence
函数定义tail
函数时(即使我从不调用sequence
),Flow类型检查上面的错误表达式而没有任何错误:
const sequence = <C> (queries : Array<Query<C, any>>) : Query<C, Array<any>> => {
if (queries.length == 0) {
return new Query(t => Promise.resolve([]))
} else {
return queries[0].bind(x => sequence(tail(queries)).map(ys => [x].concat(ys)))
}
}
我应该注意,如果我将tail
的类型更改为:
declare function tail<T,V:Array<T>>(xs: V): V;
(通过删除总和类型)
我出错了还是Flow中的错误?
答案 0 :(得分:2)
似乎肯定是一个错误。我设法缩短了失败的测试
// @flow
declare function tail<T,V:Array<T> | string>(xs: V): V;
class Query<C, T> {
run: (config: C) => Promise<T>;
constructor(runner : (config: C) => Promise<T>) {
this.run = runner
}
chain <U>(f : (a: T) => Query<C, U> ) : void {
}
}
function wat<C, T>(queries : Array<Query<C, T>>) : void {
tail(queries)
}
// $ExpectError
new Query(config => Promise.resolve(config + 1)).run({init: 2})