流类型:无法将X分配给Y,因为属性Y缺少null

时间:2019-02-19 14:50:42

标签: javascript flowtype

一个相对简单的问题,但是我一直以各种形式碰到这个问题。

这是一个示例(使用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检查,似乎无法正确地完善它。

你们将如何解决这个问题?

1 个答案:

答案 0 :(得分:0)

这是因为Flow不知道String函数可能会有什么副作用,因此在调用this._hiddenInput.current !== nullString(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用于将函数标记为 pure 的方法,有一天可能会有所帮助。