React - 流和条件渲染

React - Flow & Conditional rendering

我正在使用 Flow 和 React-Native。我遇到了 VSCode 提出的流程问题,我不知道如何更改我的方法以符合流程类型。

/* @flow */

type RandomType = {
  id: number,
  unit: string,
};

const renderData = (data: RandomType) => { return data.id };

const getRandomTypeOrEmpty = (isempty: boolean): RandomType | {} => {
    if (isempty) { return {} }
    return { id: 1, unit: 'litres'}
};

const data = getRandomTypeOrEmpty(true);
if (data && data.id ) { renderData(data) };

16: if (data && data.id ) { renderData(data) }; ^ Cannot call renderData with data bound to data because property id is missing in object type [1] but exists in RandomType [2].

这是我的问题:

我有一个函数可以为我提供 data 类型 RandomType 或者空对象{}。 然后,我必须调用一个必须采用 RandomType 参数的函数。

所以我根据 data 值和条件调用此函数。 但是,即使永远不会使用非 RandomType

的数据调用此函数,Flow 仍然会引发问题

我该如何解决这个错误?

感谢您的宝贵时间

您应该使用 maybe type 来表示可选的 属性。

type RandomNumber = {
  id?: number,
  unit?: string
};

const a: RandomNumber = {}; // works

现在你的 RandomNumber 类型的变量如果为空仍然有效。

https://flow.org/try/#0PTAEAEDMBsHsHcBQiAuBPADgU1AJQIYB2AJrALYByArmQEZYBOoAvKAN6KigCWxA-AC5QhGvQYAaTqCqFuKQaADOKBt0IBzRAF8A3MgDGsQstD4hBEuWp1GLdrsRA

试试这个


/* @flow */

type RandomType = {
  id ?: number,
  unit ?: string
};

const renderData = (data: RandomType) :number => { return data.id };

const getRandomTypeOrEmpty = (isempty: boolean): RandomType => {
    return isempty ? {} : { id: 1, unit: 'litres'}
};

const data = getRandomTypeOrEmpty(true);
if (data && data.id ) { renderData(data) };

问题是您在 getRandomTypeOrEmpty 上的 return 类型可能 returning 一个不精确的对象 {},它上面可能有任何键。这意味着它上面可能有一个 id 键,因此检查 data.id 不允许流程确定您正在处理 RandomType.

您可以 return 一个确切的空对象,然后问题就消失了:

type RandomType = {
  id: number,
  unit: string,
};

const renderData = (data: RandomType) => { return data.id };

const getRandomTypeOrEmpty = (isempty: boolean): RandomType | {||} /* return an EXACT empty object */ => {
    if (isempty) { return {}.freeze } // <-- freeze the type so it's an exact object
    return { id: 1, unit: 'litres'}
};

const data = getRandomTypeOrEmpty(true);
if (data.id ) { renderData(data) }; // <-- only need to check for presence of id

Flow link