死代码(Ramda 类型减速)中断 Flow

Dead code (Ramda type decelration) breaks Flow

我从 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))
  }
}

正确使用此定义流无法键入检查此表达式:

new Query(config => Promise.resolve(config + 1)) // config is {init: number}
.run({init: 2}).then(console.log)

Flow console

但是当我使用声明的 tail 函数定义一个 sequence 函数时(即使我从不调用 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)))
  }
}

Flow console

我应该注意到,如果我将 tail 的类型更改为:

,Flow 会正确识别类型错误
declare function tail<T,V:Array<T>>(xs: V): V;

(去掉求和类型)

Flow console

是我弄错了什么还是 Flow 中的错误?

看起来绝对是一个错误。我设法缩短了失败的测试

// @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})