gpt4 book ai didi

javascript - 使用动态函数引用时的流程错误

转载 作者:行者123 更新时间:2023-11-30 06:21:42 24 4
gpt4 key购买 nike

我在 React 项目中有一个函数,它遍历数组并将每个项目与另一个变量进行比较。现在数组中的项目可以是字符串或正则表达式。因此,我保留了一个名为 compareFn 的变量,并根据项目的类型将其引用指向 equalpatternMatch。下面是示例代码。

const equal = (privilege: string, whitelistVal: string) => privilege === whitelistVal;
const patternMatch = (privilege: string, whitelistPattern: RegExp) => whitelistPattern.test(privilege);

...

const compareFn = whitelistItem instanceof RegExp ? patternMatch : equal;
if (compareFn(privilegeItem, whitelistItem)) {
// Do something
}

使用此代码,我在第 36 行中遇到突出显示 whitelistItem 的流程错误,如下所示:

Cannot call compareFn with whitelistItem bound to whitelistPattern because string [1] is incompatible with RegExp [2].

35| const compareFn = whitelistItem instanceof RegExp ? patternMatch : equal;
36| if (compareFn(privilegeItem, whitelistItem)) {

在我看来,Flow 似乎无法识别函数引用的条件赋值。感谢您提供解决此问题的任何帮助。

我正在使用 Flow 0.71.0 和 React Native 0.55.3。

最佳答案

这是有效的:

const equal = (privilege: string, whitelistVal: string) => privilege === whitelistVal;
const patternMatch = (privilege: string, whitelistPattern: RegExp) => whitelistPattern.test(privilege);


declare function getCompareFn(
whitelistItem: RegExp
): (string, RegExp) => boolean;
declare function getCompareFn(
whitelistItem: string
): (string, string) => boolean;

function getCompareFn(whitelistItem) {
return whitelistItem instanceof RegExp ? patternMatch : equal;
}

const whitelistItem1 = /test/;
const whitelistItem2 = "test";

const privilegeItem = "test";

getCompareFn(whitelistItem1)(privilegeItem, whitelistItem1);
getCompareFn(whitelistItem2)(privilegeItem, whitelistItem2);

链接到 Try Flow

流的 declare 用于确定 getCompareFn 的精确类型签名否则很难表达。请注意流程不会强制您声明的正确性,因此您有责任仔分割析并确保声明的类型确实与函数的实现相匹配,但在本示例中,这是相当微不足道的。

不使用 declare ,这是我们可以做的:

// type alias to represent generic compare function
type CompareFn<T> = (string, T) => boolean;

function getCompareFn(
whitelistItem: RegExp | string
): CompareFn<string> | CompareFn<RegExp> {
return whitelistItem instanceof RegExp ? patternMatch : equal;
}

到目前为止一切顺利,它可以进行类型检查。 (但请注意,getCompareFn 的返回值不是 CompareFn<RegExp | string> )。不幸的是,这种 getCompareFn 的类型规范不够精确。例如,我们知道以下内容是正确的:

const f: CompareFn<string> = getCompareFn('string');

然而,flow 无法断言这一点。

更进一步,我们可能会尝试这样来解决问题:

function getCompareFn<T: RegExp | string>(whitelistItem: T): CompareFn<T> {
return whitelistItem instanceof RegExp ? patternMatch : equal;
}

这比上面好多了,因为它更精确,泛型函数 getCompareFn状态:

  1. getCompareFn(string) -> CompareFn<string>
  2. getCompareFn(RegExp) -> CompareFn<RegExp>

这正是代码的意图。一切都很好?不幸的是,这段代码没有进行类型检查。问题是T: string | RegExp ,它指出:对于 string | RegExp 类型的所有子类型, getCompareFn返回 CompareFn<T> .转化为:

  1. getCompareFn(string) -> CompareFn<string>
  2. getCompareFn(RegExp) -> CompareFn<RegExp>
  3. getCompareFn(string | RegExp) -> CompareFn<string | RegExp) ;

最后一种情况显然不成立,因为getCompareFn永远不能返回接受字符串和 RegExp 的比较函数。所以我们想表达案例 1 和案例 2,但不允许案例 3,我知道这样做的唯一工具是 declare ,因此这个答案首先概述了解决方案。

最后,通过稍微更改代码,这是一个不使用 declare 的解决方案,还有一点更惯用(在我看来):Link .

const whitelistItem1 = /test/;
const whitelistItem2 = "test";

const privilegeItem = "test";

interface TestString {
test(s: string): boolean;
};

// RegExp has method `test`, therefore structurally implements TestString

class EqualsString implements TestString {
_value: string;
constructor(value: string) {
this._value = value;
}
test(s) {
return s === this._value;
}
}

function getStringTester(whitelistItem: string | RegExp): TestString {
if (whitelistItem instanceof RegExp) {
return whitelistItem;
} else {
return new EqualsString(whitelistItem);
}
}

const t1 = getStringTester(whitelistItem1);
const t2 = getStringTester(whitelistItem2);

const b1: boolean = t1.test(privilegeItem);
const b2: boolean = t2.test(privilegeItem);

关于javascript - 使用动态函数引用时的流程错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52726598/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com