Javascript 如何防止Flowtype统一类型?

Javascript 如何防止Flowtype统一类型?,javascript,flowtype,Javascript,Flowtype,我希望有人能帮我找出我在下面的类型中缺少的东西。我创建了一个名为match的函数,它接受一个元组数组 识别后,将执行匹配功能。例如: type Fn1=(a:a,…rest:empty[])=>B; 声明导出函数匹配( xs:Array mixed]>,, …休息:空[] ):Fn1; 描述('匹配',()=>{ 类文件存在{} 类FileDoesNotExist{} 让matcher:(x:FileExists | FileDoesNotExist)=>mixed; 在每个之前(()=>{

我希望有人能帮我找出我在下面的类型中缺少的东西。我创建了一个名为
match
的函数,它接受一个元组数组 识别后,将执行匹配功能。例如:

type Fn1=(a:a,…rest:empty[])=>B;
声明导出函数匹配(
xs:Array mixed]>,,
…休息:空[]
):Fn1;
描述('匹配',()=>{
类文件存在{}
类FileDoesNotExist{}
让matcher:(x:FileExists | FileDoesNotExist)=>mixed;
在每个之前(()=>{
const whenFileExists=[FileExists,(x:FileExists)=>x];
const whenFileDoesNotExist=[FileDoesNotExist,(x:FileDoesNotExist)=>x];
matcher=match([WhenFiles,whenFileDoesNotExist]);
});
它('应该返回whenFileDoesNotExist'的实例,()=>{
//应调用包含FileDoesNotExist类的元组中的函数
预期(matcher(new FileDoesNotExist())instanceof FileDoesNotExist).toBe(true);
});

});类型变量
A
必须在
match
中使用的所有位置解析为相同的类型,这导致了问题

如果删除该参数并尝试执行Flow尝试执行的操作,则会遇到相同的问题。您希望类型
A
是最一般的情况(我称之为
Existence
):

在这里,
A
将解析为
FileExists | FileDoesNotExist
,但是使用
*
的每个地方,都可以根据用法推断为
FileExists
FileDoesNotExist


除了在中,我在任何地方都找不到这个文档,所以我不能100%确定它的语义。可能需要稍微修改一下才能完全正确地使用。

类型变量
a
必须在
match
中使用的任何地方解析为相同的类型,这就是问题的根源

如果删除该参数并尝试执行Flow尝试执行的操作,则会遇到相同的问题。您希望类型
A
是最一般的情况(我称之为
Existence
):

在这里,
A
将解析为
FileExists | FileDoesNotExist
,但是使用
*
的每个地方,都可以根据用法推断为
FileExists
FileDoesNotExist


除了在中,我在任何地方都找不到这个文档,所以我不能100%确定它的语义。可能需要稍微修改一下才能使用法完全正确。

存在主义类型是一个好主意,但它的问题是它不会在应该的时候捕捉错误。例如,如果我执行以下操作:

declare export function match<A>(
  xs: Array<[Class<*>, (x: A) => mixed]>,
  ...rest: empty[]
): Fn1<*, mixed>;

const whenFileExists = [FileExists, (x: FileExists) => x];
const whenFileDoesNotExist = [FileDoesNotExist, (x: string) => x];
matcher = fp.match([whenFileExists, whenFileDoesNotExist]);
(matcher(new FileDoesNotExist()): mixed);
虽然为每种情况写一份声明是一件痛苦的事情,但在大多数情况下,要匹配的项目不可能超过5项。我应该能够安全地为最多5个条目添加声明。转到上面的代码段,这将捕获x作为字符串,并引发以下错误:

此类型与的预期参数类型不兼容
字符串:test.js:xx


如果flow能够使用存在类型来推断这一点,那就太好了

存在主义类型是一个好主意,但它的问题是,它不会在应该的时候捕捉错误。例如,如果我执行以下操作:

declare export function match<A>(
  xs: Array<[Class<*>, (x: A) => mixed]>,
  ...rest: empty[]
): Fn1<*, mixed>;

const whenFileExists = [FileExists, (x: FileExists) => x];
const whenFileDoesNotExist = [FileDoesNotExist, (x: string) => x];
matcher = fp.match([whenFileExists, whenFileDoesNotExist]);
(matcher(new FileDoesNotExist()): mixed);
虽然为每种情况写一份声明是一件痛苦的事情,但在大多数情况下,要匹配的项目不可能超过5项。我应该能够安全地为最多5个条目添加声明。转到上面的代码段,这将捕获x作为字符串,并引发以下错误:

此类型与的预期参数类型不兼容
字符串:test.js:xx


如果flow能够使用存在类型来推断这一点,那就太好了

嗨,彼得,谢谢你的详细回复。存在类型似乎允许流推断正在使用的实际类型。这将删除我看到的错误,但不幸的是,它无法捕获我故意添加的错误。例如,如果我做了如下操作:[FileExists,(x:{id:number})=>x]。在上面的例子中,我希望它抛出一个错误,因为
x
应该是FileExists的实例,而不是对象。但“流”似乎并没有抓住这个问题。好吧,这很烦人。我能想到的另一个解决方案是为
FileExists
FileDoesNotExist
创建一个公共基类,这可能不是您想要的。然后可以使用基类作为lambda的参数类型。然后您还可以删除
*
类型并将
类型参数放回原来的位置。再次感谢您的解释。我们已经找到了一种方法来实现这一点,但这并不是最理想的(见上面的帖子)。如果您感兴趣,我在Flowtype github页面上创建了一个问题:嗨,Peter,谢谢您的详细回复。存在类型似乎允许流推断正在使用的实际类型。这将删除我看到的错误,但不幸的是,它无法捕获我故意添加的错误。例如,如果我做了如下操作:[FileExists,(x:{id:number})=>x]。在上面的例子中,我希望它抛出一个错误,因为
x
应该是FileExists的实例,而不是对象。但“流”似乎并没有抓住这个问题。好吧,这很烦人。我能想到的另一个解决方案是为
FileExists
FileDoesNotExist
创建一个公共基类,这可能不是您想要的。然后可以使用基类作为lambda的参数类型。然后您还可以删除
*
类型并将
类型参数放回原来的位置。再次感谢您的解释。我们已经找到了一种方法来实现这一点,但这并不是最理想的(参见pos)
declare export function match<A>(
  xs: Array<[Class<*>, (x: A) => mixed]>,
  ...rest: empty[]
): Fn1<*, mixed>;

const whenFileExists = [FileExists, (x: FileExists) => x];
const whenFileDoesNotExist = [FileDoesNotExist, (x: string) => x];
matcher = fp.match([whenFileExists, whenFileDoesNotExist]);
(matcher(new FileDoesNotExist()): mixed);
declare export function match<A, B>(
  xs: [[Class<A>, (x: A) => mixed], [Class<B>, (x: B) => mixed]],
  ...rest: empty[]
): (x: A | B) => mixed;

declare export function match<A, B, C>(
  xs: [[Class<A>, (x: A) => mixed], [Class<B>, (x: B) => mixed], [Class<C>, (x: C) => mixed]],
  ...rest: empty[]
): (x: A | B | C) => mixed;