我正在尝试扩展redux连接,以便它可以与特定的reducer / state一起用作装饰器,这可能不是必需的,因为redux connect可以用作装饰器,但是我很好奇为什么我不能它以我想要的方式工作。
这是我用作装饰器的HOC:
interface InjectedProps { userId: string; }
type ComponentType<P> = React.ComponentClass<P> | React.StatelessComponent<P>;
type StateToProps = (setting: ApplicationState) => InjectedProps;
export function withUserSetting(
stateToProps?: StateToProps
): <P extends InjectedProps>(WrappedComponent: ComponentType<P>) => void {
return <P extends InjectedProps>(Comp: ComponentType<P>) => {
class NewComponent extends (Component || PureComponent)<P> {
render() {
return <Comp {...this.props} />;
}
}
return connect(stateToProps)(NewComponent as any);
};
}
它工作正常,如果缺少道具,它将提醒我,这是因为它期望返回类型为'InjectedProps':
但是,我想修改hoc,以便它可以根据“ stateToProps”的返回类型来提醒我:
type AnyFunction = (...args: any[]) => any;
type ComponentType<P> = React.ComponentClass<P> | React.StatelessComponent<P>;
type StateToProps = (setting: ApplicationState) => { [key: string]: any };
export function withUserSetting<T extends AnyFunction>(
stateToProps?: StateToProps
): <P extends ReturnType<T>>(WrappedComponent: ComponentType<P>) => void {
return <P extends ReturnType<T>>(Comp: ComponentType<P>) => {
class NewComponent extends (Component || PureComponent)<P> {
render() {
return <Comp {...this.props} />;
}
}
return connect(stateToProps)(NewComponent as any);
};
}
如您所见,不再需要'InjectedProps',因此它可以具有任何道具名称,我假设由于'ReturnType'装饰器应自动识别道具,并在未为组件声明时提醒我,但是它没有任何作用:
装饰器工作正常,但是,我没有所需的类型安全性! 知道为什么它不起作用吗?
答案 0 :(得分:0)
在简化代码并更好地理解它之后,我设法使其正常运行,这是有效的版本:
type ComponentType<P> = React.ComponentClass<P> | React.StatelessComponent<P>;
type MapStateToProps<T> = (setting: ApplicationState) => T;
export function withUserSetting<T>(mapStateToProps?: MapStateToProps<T>):
<P extends T>(WrappedComponent: ComponentType<P>) => void {
return <P extends T>(WrappedComponent: ComponentType<P>) => {
return connect(mapStateToProps)(WrappedComponent as any);
};
}
现在可以像这样使用:
@withUserSetting((state) => ({ userId: state.userSetting.userId }))
或者这样:
@withUserSetting<UserProps>((state) => ({ userId: state.userSetting.userId }))
在两种方式下,如果声明中缺少属性,都会引发错误。