未知类型的流有界多态性



我正在尝试拥有一个函数,该函数将 React 组件和对象作为具有正确流类型的参数。因此,React 组件参数应该期望P类型的 props,其中P应该具有推断类型的属性themeV。我知道V是字符串的对象,但它仍然可以是不同的类型(即{ button: string }{ checkbox: string }不同)。第二个参数的类型应为V

该函数的要点是获取一个需要 proptheme的 React 组件(它只是专门针对该 React 组件的字符串对象),并使用第二个参数作为该 prop,返回一个新的 React 组件,它不需要那个themeprop(因为它已经被赋予了)。

我已经做了几次尝试,但仍然没有找到一些工作。

/* @flow */
type FunctionComponent<P> = (props: P) => ?React$Element<any>;
type ClassComponent<D, P, S> = Class<React$Component<D, P, S>>;
type Component<P> = FunctionComponent<P> | ClassComponent<any, P, any>;
type ThemeType = { [className: string]: string };
function mergeTheme<P: { theme: ThemeType }, V: $PropertyType<P, 'theme'>>(
BaseComponent: Component<P>,
injectedTheme: V
): FunctionComponent<$Diff<P, { theme: V }>> {
const ThemedComponent = ownProps => <BaseComponent {...ownProps} theme={injectedTheme} />;
ThemedComponent.displayName = 'Themed(' + BaseComponent.displayName + ')';
return ThemedComponent;
}

流错误

12:     const ThemedComponent = ownProps => <BaseComponent {...ownProps} theme={injectedTheme} />;
^ props of React element `BaseComponent`. Expected object instead of
12:     const ThemedComponent = ownProps => <BaseComponent {...ownProps} theme={injectedTheme} />;
^ object type
12:     const ThemedComponent = ownProps => <BaseComponent {...ownProps} theme={injectedTheme} />;
^ props of React element `BaseComponent`. Expected object instead of
12:     const ThemedComponent = ownProps => <BaseComponent {...ownProps} theme={injectedTheme} />;
^ some incompatible instantiation of `P`

试用流示例

这也是我各种尝试的要点

我真正的目标实际上是让新的 React 组件接受一个可选的theme参数,然后我会将其与上面示例中的injectedTheme合并,但首先是婴儿步骤。

这似乎目前效果很好。不确定它是否正确

type FunctionComponent<P, C> = (props: P, context: C) => ?React$Element<any>;
type ClassComponent<D, P, S> = Class<React$Component<D, P, S>>;
declare function mergeTheme<P: { theme: *, [propName: any]: any }, V: $PropertyType<P, 'theme'>>(
BaseComponent: ClassComponent<*, P, *>,
injectedTheme: V
): FunctionComponent<$Diff<P, { theme: V }> & { theme?: $Shape<V> }, *>;
declare function mergeTheme<P: { theme: *, [propName: any]: any }, V: $PropertyType<P, 'theme'>>(
BaseComponent: FunctionComponent<P, *>,
injectedTheme: V
): FunctionComponent<$Diff<P, { theme: V }> & { theme?: $Shape<V> }, *>;
function mergeTheme(BaseComponent, injectedTheme) {
const ThemedComponent = ownProps => {
let theme = injectedTheme;
if (ownProps && ownProps.theme) {
const ownTheme = ownProps.theme;
theme = Object.keys(ownTheme)
.filter(key => !!injectedTheme[key])
.reduce((accum, key) => {
accum[key] = classnames(ownTheme[key], injectedTheme[key]);
return accum;
}, { ...ownTheme, ...injectedTheme });
}
return <BaseComponent {...ownProps} theme={theme} />;
};
const currName = BaseComponent.displayName || BaseComponent.name;
ThemedComponent.displayName = `Themed(${currName})`;
return ThemedComponent;
}

编辑

所以这并不完全有效。以此示例代码为例:

type Theme = {|
someClass: string,
anotherClass: string
|};
type Props = { someProp: string, theme: Theme };
const SomeComponent = (props: Props) => <div className={props.theme.someClass}>{props.someProp}</div>;
const ThemedComponent = mergeTheme(SomeComponent, { someClass: 'world', anotherClass: 'idhgo' });
// The line below should work but instead flow complains
const el1 = <ThemedComponent someProp="hello" theme={{ someClass: 'hello' }} />

有问题的流错误:

47: type Props = { someProp: string, theme: Theme };
^ property `anotherClass`. Property not found in
52: const el1 = <ThemedComponent someProp="hello" theme={{ someClass: 'poop' }} />
^ object literal

这是"尝试流程"的链接

最新更新