为什么流类型没有推断出正确的泛型类型



我们一直在尝试用 Flow 在代码库中的 React 中注释我们的高阶组件,但没有取得多大成功。

我们有

  • adapt接受适配器作为参数的高阶组件。
  • adaptDataProp接受仅在props.data对象上调用的数据适配器

这是没有实现 Flow 的实现

function adapt(adapter) {
return (Component) {
return (props) => <Component {...adapter(props)} />;
};
}
function adaptDataProp(dataAdapter) {
function adapter(inputProps) {
const { data, ...rest } = inputProps;
return ({ ...dataAdapter(data), ...rest });
}
return adapt(adapter);
}
const TestFunction = ({ moo, className }) => <div className={className}>{ moo }</div>
const dataAdapter = ({ a }) => ({ moo: a });
const AdaptedTestFunction = adaptDataProp(dataAdapter)(TestFunction);
// rendering
<AdaptedTestFunction data={{ a: 'a' }} className='b' />

以下是我们拥有的测试用例:

// Test example 1: Should fail as data prop passed in is wrong
<AdaptedTestFunction data={{ b: 'b' }} className='b' /> 
// Test example 2: Should fail as missing className prop
<AdaptedTestFunction data={{ a: 'a' }} />
// Test example 3: Should pass  
<AdaptedTestFunction data={{ a: 'a' }} className='b' /> 

我们对上述内容的流注释使用泛型类型。

我们有adaptadaptDataProp在单独的文件中。

// Functional Component for React
type FunctionalComponent<Props> = (props: Props) => ?React$Element<any>;
// Union of Functional Component or a Class React Component
type ComponentDefinition<DefaultProps, Props, State> = FunctionalComponent<Props> | Class<React$Component<DefaultProps, Props, State>>;

type AdaptReturnType<AdaptedProps, Props> = ComponentDefinition<void, AdaptedProps, *> => FunctionalComponent<Props>;
function adapt<
Props: Object, 
AdaptedProps: Object
>(adapter: Props => AdaptedProps): AdaptReturnType<AdaptedProps, Props> {
return (Component: ComponentDefinition<void, AdaptedProps, *>): FunctionalComponent<Props> => {
return (props: Props) => <Component {...adapter(props)} />;
};
}
function adaptDataProp<
Data: Object,
AdaptedData: ?Object,
Rest: Object
>(dataAdapter: Data => AdaptedData): 
AdaptReturnType<
Rest & AdaptedData,
Rest & { data: Data }
> {
function adapter(inputProps: Rest & { data: Data }): Rest & AdaptedData {
const { data, ...rest } = inputProps;
return ({ ...dataAdapter(data), ...rest });
}
return adapt(adapter);
}
type Props = {
moo: string,
className: string
};
type AdaptedProps = {
moo: string
};
type Data = {
a: string
};
const TestFunction = ({ moo, className }: Props) => <div className={className}>{ moo }</div>
const dataAdapter = ({ a }: Data): AdaptedProps => ({ moo: a });
const AdaptedTestFunction = adaptDataProp(dataAdapter)(TestFunction);

但是,对于测试示例 3,我收到以下错误:

const TestFunction = ({ moo, className }: Props) => <div className={className}>{ moo }</div>
^ property `moo`. Property not found in
<AdaptedTestFunction data={{ a: 'a' }} className='b' /> 
^ props of React element `AdaptedTestFunction`

我们希望上述内容能够通过,因为 AdaptedTest 只有在不符合Rest & { data: Data }时才应该失败。

这是 Flow 本身的问题还是我做错了什么?

警告:Flow 不会推断泛型类型。

如果您希望某些内容具有泛型类型,请对其进行批注。否则,Flow 可能会推断出比您预期的多态性更低的类型。

通过: https://flow.org/en/docs/types/generics/

最新更新