Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/eclipse/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何在流中使用相同泛型类型的值对泛型函数进行类型检查_Javascript_Reactjs_Generics_Flowtype - Fatal编程技术网

Javascript 如何在流中使用相同泛型类型的值对泛型函数进行类型检查

Javascript 如何在流中使用相同泛型类型的值对泛型函数进行类型检查,javascript,reactjs,generics,flowtype,Javascript,Reactjs,Generics,Flowtype,我们将Flow与React一起使用,我们编写了这个下拉包装器,它为我们做了一些事情 到目前为止,这个下拉列表只需要处理numberid,但最近,我们还必须添加对stringid的支持 由于不想重写所有内容,我们考虑在props中使用泛型类型参数,以便id(和onChange处理程序)使用该泛型类型 然而,我们似乎无法正确使用变更处理程序。当尝试调用处理程序时,我们会收到一个关于发送它的值类型的流错误(无论是number还是string),告诉我们该类型与T不兼容: 无法调用'value'绑定到'

我们将Flow与React一起使用,我们编写了这个下拉包装器,它为我们做了一些事情

到目前为止,这个下拉列表只需要处理
number
id,但最近,我们还必须添加对
string
id的支持

由于不想重写所有内容,我们考虑在props中使用泛型类型参数,以便id(和onChange处理程序)使用该泛型类型

然而,我们似乎无法正确使用变更处理程序。当尝试调用处理程序时,我们会收到一个关于发送它的值类型的流错误(无论是
number
还是
string
),告诉我们该类型与
T
不兼容:

无法调用'value'绑定到'value'的'handler',因为字符串[1]与'T'不兼容。

电话号码也是一样的

我们相信,如果我们成功地检查其中一个泛型值的类型,它将使用我们的道具中相同的泛型类型为每个元素折叠该类型。这是:

type Props<T : string | number> = {
  options?: Array<{id: T, displayValue: string}>,
  onValueChange?: (value: T | null) => mixed,
}
因此,我的问题是:是否有可能确定函数参数的泛型类型,以便我们可以根据需要使用它,而不会出现错误

如果答案是肯定的,那么我们在代码中犯了什么错误,阻止了类型检查按需要工作

如果答案是否定的,有没有比将我们的值转换为
any
更好的方法让我们的处理程序接受它

我在这篇文章中写了一个简单的工作示例,因此您可以看到实时错误以及预期的使用情况(请注意,使用情况部分中的错误是预期的:它们显示使用通用组件可以按照我们希望的方式工作,即使使用值不起作用)。重要的错误是错误输出中的前两个


提前感谢您的帮助

我认为你对这个问题想得太多了。。看起来您在将event.target.value的类型声明为“string”而不是“T”时犯了一个小错误

试试这个

export class DropDown<T : string | number> extends React.Component<Props<T>, {}> {
  handleChange = (event: {target: {value: T}}) => { // not {value: string}
    if (!this.props.onValueChange) return
    const handler = this.props.onValueChange
    const value = event.target.value
    handler(value)
  }
}  
导出类下拉列表扩展了React.Component{
handleChange=(事件:{target:{value:T}})=>{//not{value:string}
如果(!this.props.onValueChange)返回
const handler=this.props.onValueChange
常量值=event.target.value
处理程序(值)
}
}  

我希望这对你有帮助

谢谢你提出这个非常有趣的问题! 不幸的是,我认为现在不可能通过细化数组中第一个元素的类型来细化类型T。当我们使用以下语句时,可以看到这一点:

if (firstElement) {
  if (typeof firstElement.id === 'string') {
    const refined: string = firstElement.id;
    const notRefined: T = refined; // Errors
    const alwaysWorks: T = firstElement.id;
  }
  const alwaysWorks: T = firstElement.id;
}
第二个赋值错误。有趣的是,这可以通过将第一个赋值也标记为
T
来解决,这表明了流是如何工作的:流本身并没有细化类型,它细化了值的类型标签。我认为您已经正确地得出结论,您需要做的是优化回调函数的值。但是这不起作用,因为我们不能对函数进行任何运行时检查(除了可能获取它们的参数数量)

所以我们了解到,流还不够好。当您深入使用Flow时,您可能会不时注意到这一点:很难表达您想要做的事情。我不确定是流出错了,还是只是JavaScript很难输入。无论如何,作为一种解决方案,我想建议您只需使用
函数
注释处理程序变量。函数在某种程度上是一种任意类型的函数,它使函数更加通用。我们知道代码是有效的(请参阅我的更正,进行空检查,然后检查
id
属性,而不是对象),外部接口非常明确地说明了类型。有时候,API才是最重要的,在内部我们必须进行一些修改。这很好(例如,我们可以在流行项目中看到很多)


奖励:如果你喜欢函数式编程,看看如何玩弄类型来创造一种没有运行时开销的可能类型的幻觉,因为它实际上只是
null

你的意思是拥有
firstElement.id
?@loganfsmyth确实,目的是引用
.id
。我刚刚更新了问题和流程的Try snippet链接,以使用正确的代码。非常感谢。你好谢谢你的帮助!但是,
事件
的类型声明没有问题。
事件
的实际类型是
合成输入事件
,其中
实际上是一个字符串。我更改了类型,因为Flow Try不知道这两种类型中的任何一种,但我使用的声明正确地键入了事件。此外,错误清楚地知道我试图传递给处理程序的
string
number
的类型,以及
T
。您的建议确实可以修复错误,但是
value
永远不会是一个数字,因此它与实际情况不符,可能会导致以后出现错误。我明白了,谢谢!事实上,令人遗憾的是,我无法用JavaScript对函数本身进行类型检查。同样令人遗憾的是,Flow无法在我检查了它的一个实例后立即折叠整个泛型类型,但是感谢您的澄清!我们将在处理程序上使用
函数
,或者在值上使用
任意
,正如您所说的,它至少是内部的,所以我们仍然可以在外部使用强类型事件处理程序。谢谢你给我的链接,我会偶尔试试的!
if (firstElement) {
  if (typeof firstElement.id === 'string') {
    const refined: string = firstElement.id;
    const notRefined: T = refined; // Errors
    const alwaysWorks: T = firstElement.id;
  }
  const alwaysWorks: T = firstElement.id;
}