【问题标题】:Typesafe react decorator not recognizing the ReturnType of the passed functionTypesafe反应装饰器无法识别传递函数的ReturnType
【发布时间】:2019-05-29 06:27:52
【问题描述】:

我正在尝试扩展 redux connect 以便它可以与特定的 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);
  };
}

它工作正常,如果缺少 Props,它会提醒我,那是因为它期望返回类型为 '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”装饰器应该自动识别道具并在没有为组件声明时提醒我,但是它没有任何作用:

装饰器工作正常,但是,我没有我正在寻找的类型安全! 知道为什么它不起作用吗?

【问题讨论】:

    标签: reactjs typescript decorator


    【解决方案1】:

    在简化代码,更好地理解之后,我设法使它工作,这是工作版本:

    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 }))
    

    在这两种情况下,如果声明中缺少属性,则会引发错误。

    【讨论】:

      猜你喜欢
      • 2016-07-23
      • 2021-10-22
      • 2022-01-16
      • 2021-11-21
      • 2012-09-28
      • 2021-11-15
      • 2017-09-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多