【问题标题】:Typescript overloads with generics, type inference and React Components带有泛型、类型推断和 React 组件的 Typescript 重载
【发布时间】:2021-11-19 12:08:34
【问题描述】:

为垃圾问题名称道歉。以下是详细信息。

我有一个 HoC/Mixin 函数

export function MyMixin<TOriginalProps>(WrappedComponent: React.ComponentClass<TOriginalProps & IExtraProps>): React.ComponentClass<TOriginalProps> {
  return class extends React.Component<TOriginalProps> {
    public render() {
      const value = "something irrelevent to the question"
      const props = {...this.props, extraProp: value}
      return <WrappedComponent {...props} />;
    }
  }
}

export interface IExtraProps {
  extraProp: string;
}

现在这对于拥有自己的 props 的组件非常有用,例如

class MyComponent extends React.Component<MyProps & IExtraProps, MyState>

MyMixin(MyComponent) // this returns React.ComponentClass<TMyProps,any>

但是对于没有任何道具的组件(除了“混合”的道具)它给了我一些奇怪的东西

class MyComponentNoProps extends React.Component<IExtraProps, MyState>

MyMixin(MyComponentNoProps) // this return React.ComponentClass<{children?: React.Node; extraProp: string;}, any>

我已尝试调整 MixinFunction 以采用类型参数的默认值,但我就是无法采用。

任何想法我如何获得一个函数(重载也可以)来处理这个?

我尝试了一个没有 TOriginalProps 类型的重载,但它没有正确解析。如果我先定义它,那么每个人都会使用它,而我应该有道具的组件却没有。如果我第二个定义它,没有人使用它。

我猜这与我使用 React 的事实有关,因为它可以推断出这个奇怪的 {children: React.Node; extraProps: string} 来自某处的类型(

【问题讨论】:

    标签: reactjs typescript mixins higher-order-components react-tsx


    【解决方案1】:

    IExtraProps 为目标的重载版本似乎会产生您正在寻找的行为:

    interface MyProps {
      originalProp: number;
    }
    
    interface IExtraProps {
      extraProp: string;
    }
    
    interface MyState {
      value: string;
    }
    
    export function MyMixin(
      WrappedComponent: React.ComponentClass<IExtraProps>
    ): React.ComponentClass;
    
    export function MyMixin<TOriginalProps>(
      WrappedComponent: React.ComponentClass<TOriginalProps & IExtraProps>
    ): React.ComponentClass<TOriginalProps>;
    
    export function MyMixin(
      WrappedComponent: React.ComponentClass<any>
    ): React.ComponentClass {
      return class extends React.Component {
        public render() {
          const value = "something irrelevent to the question"
          const props = {...this.props, extraProp: value}
          return <WrappedComponent {...props} />;
        }
      }
    }
    
    class MyComponent extends React.Component<MyProps & IExtraProps, MyState>{};
    class MyComponentNoProps extends React.Component<IExtraProps, MyState>{};
    
    const Test1 = MyMixin(MyComponent);
    const Test2 = MyMixin(MyComponentNoProps);
    
    function App() {
      return (
        <>
          <Test1 originalProp={42} /> // OK 
          <Test2 /> // OK
        </>
      )
    }
    

    【讨论】:

    • 感谢您的建议,但是当我尝试这个时,我没有得到相同的结果。本质上 Component 和 ComponentNoProps 都会调用首先定义的重载,因为两者都可以满足。两者都实现了 IExtraProps,因此可以应用非通用的“固定”IExtraProps 方法,并且由于 TOriginalProps 可以只是 {},第二个重载似乎也匹配两者
    • @Dave 我无法重现您的问题 - playground。您能否尝试创建一个失败的最小测试用例?
    猜你喜欢
    • 1970-01-01
    • 2021-07-28
    • 2019-09-17
    • 2017-10-04
    • 2016-12-05
    • 2018-01-18
    • 1970-01-01
    • 1970-01-01
    • 2020-12-01
    相关资源
    最近更新 更多