我有一个以下列方式(无类型)实现的“高阶组件”。
const Themeable = (mapThemeToProps) => {
return (WrappedComponent) => {
const themedComponent = (props, { theme: appTheme }) => {
return <WrappedComponent
{...props}
theme={merge(
{},
defaultTheme,
appTheme,
mapThemeToProps(merge(defaultTheme, appTheme))
)}
>
}
themedComponent.contextTypes = { theme: PropTypes.object };
return themedComponent;
}
}
总结一下它的作用,它需要一个 mapThemeToProps
函数。这将接收通过合并 defaultTheme
(由我的库提供)和 appTheme
(由 ThemeProvider
组件通过上下文提供)创建的主题参数。然后它将创建一个扩展的 Theme
并将其作为名为 theme
的 prop 传递给组件。实际上,它将按如下方式使用(在此范围内称为 Themeable
):
const mapThemeToProps = (theme) => ({
background: theme.palette.dark,
color: theme.text.light,
});
function Greeting({ theme: { background, color } }) {
return (
<div style={{ background, color }}>
Hello World!
<div>
)
}
export default Themeable(mapThemeToProps)(Greeting);
我很难为这个函数开发一个合适的类型。 I found this pattern is very similar to something along the lines of connect
from react-redux
so have been working from their typings作为我的出发点。无论如何,我有点迷茫,这基本上就是我所在的位置:
import { Theme } from 'types/Theme';
interface ThemeableComponentEnhancer {
<P>(component: React.ComponentType<P>): React.ComponentClass<Pick<P, "theme"> & { theme: Theme }> & { WrappedComponent: React.Component<P>}
}
export interface Themeable {
// calling it with no parameters returns a basic theme.
(): Theme;
// calling it with a function
<TTheme = {}>(mapThemeToProps: MapThemeToPropsParam<TTheme>): ComponentEnhancer<{ theme: TTheme }>;
}
interface MapThemeToProps<TTheme> {
(theme: TTheme): TTheme;
}
interface MapThemeToPropsFactory<TTheme> {
(theme: Theme): MapThemeToProps<TTheme>;
}
type MapThemeToPropsParam<TTheme> = MapStateToPropsFactory<TTheme>
我很难理解这个问题。这将如何在 TypeScript 中完成?
最佳答案
主题.ts
export interface Theme {
palette: {
primary: string;
secondary: string;
};
}
export const theme: Theme = {
palette: {
primary: 'red',
secondary: 'yellow'
}
};
Rect
组件示例 Theme
import * as React from 'react';
import { Theme } from '../theme/Theme';
import withTheme, { MapThemeToProps } from '../theme/withTheme';
export interface RectThemeProps {
titleColor?: string;
bodyColor?: string;
}
export interface RectProps extends RectThemeProps {
content?: string;
}
export class Rect extends React.Component<RectProps> {
render() {
const {titleColor, bodyColor, content} = this.props;
return <div>{content && content}</div>;
}
}
const mapThemeToProps: MapThemeToProps<
RectThemeProps,
Theme
> = (theme) => {
return {
titleColor: theme.palette.primary,
bodyColor: theme.palette.secondary
};
};
export default withTheme(mapThemeToProps)(Rect);
withTheme.ts
import * as React from 'react';
const ID = '__context_id__';
export interface MapThemeToProps<M, T> {
(theme: T): M;
}
export interface withTheme {
<M, T>(mapThemeToProps: MapThemeToProps<M, T>):
(c: React.ComponentType<M>) => React.ComponentType<M>;
}
export default <M, T>(
mapThemeToProps: MapThemeToProps<M, T>
) => (Component: React.ComponentType<M>) => {
return class extends React.Component<M> {
render() {
const theme = this.context[ID];
return (
<Component
{...this.props}
{...mapThemeToProps(theme.getTheme())}
/>
);
}
};
}
关于javascript - 将类型定义添加到将 props 注入(inject)组件的 HOC,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47701205/