網站搜尋

javascript - 使用 Enzyme 和 TypeScript 的淺層高階組件


我有一個 HOC 要測試,在淺層掛載時我應該調用一些類方法:

it('Should not call dispatch', () => {
        const dispatch = jest.fn()
        const WrappedComponent = someHoc(DummyComponent)
        const instance = shallow(
          <WrappedComponent
            dispatch={dispatch}
          />,
        ).instance() as WrappedComponent
        instance.someMethod()
        expect(dispatch).toHaveBeenCalledTimes(0)
})

測試運作正常,但 TS 編譯器拋出錯誤

 Cannot find name 'WrappedComponent'.

這是正確的,因為 WrappedComponent 不是一種類型或類別,但是如果我移除它

 as WrappedComponent

行,TS 會拋出錯誤

Property 'someMethod' does not exist on type 'Component<{}, {}, any>'.

另外,如果我把那一行改成……,就無法編譯了

as typeof WrappedComponent

someHoc 描述:

import ...

interface State {
  /*state*/
}

interface Props {
  dispatch: Dispatch<Action>
  /*props*/
}

export someHoc = <T extends {}>(
  ChildComponent: React.ComponentClass<T>,
) => {
  class Wrapper extends React.PureComponent<T & Props, State> {

    someMethod = () => {
       /*do smth*/
    }

    render() {
      return (
        <div>
          <ChildComponent {...this.props} />
        </div>
      )
    }
  }

  return Wrapper
}

我該如何輸入 HOC 實例?謝謝。

答案#1

預期具有可參數化的可變回傳值類型的函數是泛型。shallow 是一個泛型:

export function shallow<C extends Component, P = C['props'], S = C['state']>(node: ReactElement<P>, options?: ShallowRendererProps): ShallowWrapper<P, S, C>;
export function shallow<P>(node: ReactElement<P>, options?: ShallowRendererProps): ShallowWrapper<P, any>;
export function shallow<P, S>(node: ReactElement<P>, options?: ShallowRendererProps): ShallowWrapper<P, S>;

它可能應該被用作:

const instance = shallow<typeof WrappedComponent>(
  <WrappedComponent
    dispatch={dispatch}
  />,
).instance();

目前在 Enzyme 的類型定義中,使用泛型參數來推斷 ShallowWrapper 中的組件類型似乎存在問題。

在測試中保護類型安全的一種變通方法是斷言類型:

const instance = shallow(
  <WrappedComponent
    dispatch={dispatch}
  />,
)
.instance() as any as InstanceType<typeof WrappedComponent>;

答案#2

這不是關於 HOC 的問題,但以防有人在谷歌搜尋好幾個小時後找到這個,試試將 @types/react 更新到最新版本(我從 18.0.14 更新到 18.2.38)。

這讓我可以使用(未修改的)

const about = shallow(<About />);

給定

export default function About() {
  const foo = true;
  return (
    <div>Blabla</div>
  )
}

毫無問題。