Typesafe反应装饰器无法识别传递函数的ReturnType

问题描述 投票:2回答:1

我正在尝试扩展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);
  };
}

它工作正常,如果Props丢失,它会提醒我,那是因为它期望返回类型'InjectedProps':

enter image description here

但是,我想修改一下,所以它可以根据'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'装饰器应该自动识别道具并提醒我,如果它没有为组件声明,但它没有'有任何影响:

enter image description here

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

reactjs typescript decorator
1个回答
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 }))

在这两种方式中,如果声明中缺少某个属性,则会引发错误。

© www.soinside.com 2019 - 2024. All rights reserved.