一个相对简单的问题,但我不断以各种形式碰撞。
这是一个例子(用try-flow测试):
import * as React from 'react';
type Props = {
value: string | number
}
export default class Example extends React.Component<Props> {
_hiddenInput: { current: React.ElementRef<'input'> | null };
value(val: number) {
if (this._hiddenInput.current !== null) {
this._hiddenInput.current.value = String(1234);
}
}
}
这里的_hiddenInput.current
是一个"maybe-type"对象属性,使用if-not-null检查似乎没有得到正确的改进。
你们怎么解决这个问题?
这是因为Flow不知道String
函数可能具有什么副作用,因此当你调用this._hiddenInput.current !== null
(在赋值之前发生)时,String(1234)
细化无效。考虑这个人为的例子:
export default class Example extends React.Component<Props> {
_hiddenInput: { current: React.ElementRef<'input'> | null };
value(val: number) {
if (this._hiddenInput.current !== null) {
this._hiddenInput.current.value = String(1234);
}
}
}
const example = new Example();
example._hiddenInput = { current: elementRef };
window.String = function(input) {
example._hiddenInput.current = null;
return `${input}`;
};
// Throws, because the String-function above will be called between
// refining the nullable type and assigning to it.
example.value(1)
您可以使用Flow知道没有副作用的内容替换函数调用
this._hiddenInput.current.value = `${1234}`
或者您可以在分配给其属性之前将容器对象“保护”为局部变量
const {current} = this._hiddenInput
if (current !== null) {
current.value = String(1234);
}
请参阅文档中的Refinement Invalidations。
当然,String
函数实际上并没有做这样的事情,但目前Flow没有任何方法可以知道这一点。有一种feature request可以将功能标记为纯粹,有朝一日可能有所帮助。