【问题标题】:Condition Flow's return type on the input parameter type输入参数类型上的条件流的返回类型
【发布时间】:2017-12-03 02:58:25
【问题描述】:

有没有办法在流中正确调整输入参数的返回类型?

以下函数是一个简单的可选递归,对于流解析来说应该不会太难,但我无法让它工作:

type XYpos = {| x: number, y: number |}
type RelativeCoordinates = {...XYpos} | Array<{...XYpos}>; // Use spread to loose the exact type
type MappedCoordInput = XYpos | Array<XYpos>;
function getMappedCoords(position: RelativeCoordinates, 
                         width: number, 
                         height: number): MappedCoordInput {
  if (position instanceof Array) {
    return position.map(p => getMappedCoords(p, width, height));
  }

  return {
    x: position.x * width,
    y: position.y * height,
  };
}

这给出了 Flow 中的错误(here 是“Flow try”):

6:     return position.map(p => getMappedCoords(p, width, height));
              ^ array type. Has some incompatible type argument with
3: type MappedCoordInput = XYpos | Array<XYpos>;
                                   ^ array type
    Type argument `T` is incompatible:
        6:     return position.map(p => getMappedCoords(p, width, height));
                                        ^ array type. Inexact type is incompatible with exact type
        3: type MappedCoordInput = XYpos | Array<XYpos>;
                                                 ^ object type

我也玩过泛型,但这似乎没有帮助:

type XYpos = {| x: number, y: number |}
type CoordInput = XYpos | Array<XYpos>;
function getMappedCoords<P: CoordInput>(position: P, 
                         width: number, 
                          height: number): CoordInput {
  if (position instanceof Array) {
    return position.map(p => getMappedCoords(p, width, height));
  }

  return {
    x: position.x * width,
    y: position.y * height,
  };
}

更新

强制转换解决了直接错误,但没有解决有关通过输入参数解析返回类型的问题:

type XYpos = {| x: number, y: number |}
type RelativeCoordinates = {...XYpos} | Array<{...XYpos}>;
type MappedCoordinates = XYpos | Array<XYpos>;
function getMappedCoords(
  position: RelativeCoordinates,
  width: number,
  height: number,
): MappedCoordinates {
  if (position instanceof Array) {
    const ret = position.map(p => getMappedCoords(p, width, height));
    return ((ret: any): Array<XYpos>);
  }

  const truePos: XYpos = {
    x: position.x * width,
    y: position.y * height,
  };
  return truePos;
}

const pos: XYpos = getMappedCoords({ x: 1, y: 1}, 2, 2);
const arrayXpos: Array<XYpos> = getMappedCoords([{x: 1, y: 1}], 2, 2);

Flow测试平台依旧complains:

22: const pos: XYpos = getMappedCoords({ x: 1, y: 1}, 2, 2);
                       ^ array type. Inexact type is incompatible with exact type
22: const pos: XYpos = getMappedCoords({ x: 1, y: 1}, 2, 2);
               ^ object type
23: const arrayXpos: Array<XYpos> = getMappedCoords([{x: 1, y: 1}], 2, 2);
                                    ^ object type. This type is incompatible with
23: const arrayXpos: Array<XYpos> = getMappedCoords([{x: 1, y: 1}], 2, 2);
                     ^ array type

【问题讨论】:

  • 为什么不简单地使用两个不同的函数?!
  • @JonasW。是的 - 这就是我所说的廉价后备解决方案:-D
  • 打字的感觉是为了让你的代码安全。这些多型男根本找不到错误,所以很没意思……
  • @JonasW。我同意这种编码风格有好处,但问题不在于编码风格。有很多库有类似的问题,除非我们想重写所有库,否则如果 Flow 允许更大的灵活性以便可以通过适当的 Flow 类型扩展这些库,那就太好了。
  • 为什么还要输入它们呢?

标签: javascript flowtype


【解决方案1】:

因为按照定义,当您的函数接受一个数组作为位置时,映射后该数组中每个元素的类型是MappedCoordInput。也就是说 position.map 可以是数组数组,这与函数的返回类型不兼容——它只是一个对象数组,而不是对象数组。

按照目前的编码,[[[{x: 1, y: 1}]]] 是一个有效的输入。但是,它不会运行Array&lt;XYPos&gt;。它将返回Array&lt;Array&lt;Array&lt;XYPos&gt;&gt;&gt;,与MappedCoordInput的返回类型不匹配。

【讨论】:

  • 输入不应该允许这样,问题是是否可以根据输入的返回类型进行条件
  • 公平到输​​入不允许它,但尽管输入的定义,它说它可以将其作为输出返回。
猜你喜欢
  • 2020-10-27
  • 1970-01-01
  • 1970-01-01
  • 2019-10-29
  • 1970-01-01
  • 2019-06-07
  • 1970-01-01
  • 2021-11-10
  • 1970-01-01
相关资源
最近更新 更多