简体   繁体   English

flowtype:如何通过参数计数/类型重载函数返回类型?

[英]flowtype: how can i overload function return types by argument count/types?

i want to define an overloaded function like我想定义一个重载函数,如

function first(n?: number) {
  if (number === undefined) {
    // returns a single Item
    return items[0];
  }

  // returns an array of Item
  return items.slice(0, n);
}

so that these statements type check:以便这些语句类型检查:

const item: Item = first(); // no args, so return type is Item
const items: Array<Item> = first(5); // number arg, so return type is Array<Item>

flow knows that the first call to first is going to result in n === undefined (since it would complain if undefined wasn't valid for n ) and it understands that it will then take the if branch, so i would think it could infer the return type is Item , but everything i've tried either lets anything pass or always fails.流动知道第一个电话first会导致n === undefined (因为如果它会抱怨undefined是无效n )和它知道它会再取如果分支,所以,我觉得它可能推断返回类型是Item ,但我尝试过的一切要么让任何事情通过,要么总是失败。

any idea if this is possible?知道这是否可能吗? thanks in advance internet.提前感谢互联网。

I don't have a complete solution for you, but I got partway there:我没有给你一个完整的解决方案,但我已经做到了:

const items = [1, 2, 3];

type FirstType = ((_: void) => number) & ((n: number) => Array<number>);

const first: FirstType = (n?: number) => {
  if (n === undefined) {
    // returns a single Item
    return (items[0]: any);
  } else {
    // returns an array of Item
    return (items.slice(0, n): any);
  }
}

const a: number = first();
const b: Array<number> = first(2);

( tryflow ) 尝试流程

The & is an intersection type, and it means that first must satisfy both of those types. &是一个交集类型,这意味着first必须满足这两种类型。 You can see that the calls to first() typecheck the way you want.您可以看到对first()的调用以您想要的方式进行类型检查。

Unfortunately, it does not seem like Flow is currently able to typecheck the body of first .不幸的是,Flow 目前似乎无法对first的正文进行类型检查。 Note that I had to cast the return values through any to escape the typechecker.请注意,我必须通过any强制转换返回值才能转义类型检查器。 If you are willing to forgo typechecking in the body of your function, you can at least get it where the functions are called.如果您愿意在函数体中放弃类型检查,您至少可以在调用函数的地方得到它。

This may not work in the version of Flow that was current when you wrote OP, but trying against the latest version, I just discovered you can use declare function even in source files to avoid the horrific syntax of ((_: void) => number) & ((n: number) => Array<number>) .这可能不适用于您编写 OP 时当前的 Flow 版本,但是尝试针对最新版本时,我发现您甚至可以在源文件中使用declare function来避免((_: void) => number) & ((n: number) => Array<number>)

type Item = number;
const items: Array<Item> = [0, 1, 2, 3, 4];

declare function first(): Item;
declare function first(n: number): Array<Item>;
function first(n?: number): Item | Array<Item> {
  if (n === undefined) {
    // returns a single Item
    return items[0];
  }

  // returns an array of Item
  return items.slice(0, n);
}

const item: Item = first(); // no args, so return type is Item
const items2: Array<Item> = first(5); // number arg, so return type is Array<Item>

Try Flow link 试试 Flow 链接

For class methods, the only way I've found is to declare the field type separately with the ugly & syntax (doesn't matter whether you use declare before the field declaration or not):对于类方法,我发现的唯一方法是使用丑陋的&语法单独声明字段类型(是否在字段声明之前使用declare无关紧要):

class Foo {
  foo: ((x: number) => string) & ((x: string) => number)
  foo(x: number | string): number | string {
    if (typeof x === 'number') return String(x)
    else return Number(x)
  }
}

const foo = new Foo()
const a: number = foo.foo('1')
const b: string = foo.foo(2)

Try Flow link 试试 Flow 链接

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM