1

TL;DNR:我使用的是 TypeScript 3.3.3。有没有更好的方法来声明从 HOC 注入的我需要的道具,而不会使它们对消耗我的组件的代码可见?


withNamespaces考虑一个用HOC装饰的基本组件。使用的库和 HOC 是任意的,我在使用任何遵循此模式的组件时都遇到了这个问题。类组件也有点问题,但这里我将重点介绍函数。

// MyComponent.tsx
import * as React from 'react'
import { withNamespaces, WithNamespaces } from 'react-i18next'


const MyComponent: React.FunctionalComponent = ({ children, t }) => (
  <a title={t('my translated text')}>{children}</a>
)

export default withNamespaces('my-component')(MyComponent)

我有第二个文件,其中包含对我的组件的测试。

// MyComponent.spec.tsx
import * as React from 'react'
import { shallow } from 'enzyme'
import MyComponent from './MyComponent'

it('should render', () => {
   const wrapper = shallow(<MyComponent>Test</MyComponent>)

   expect(wrapper.toExist()).toBeTruthy()
})

现在这不会编译,因为t我的道具中没有定义。我可以尝试通过多种方式解决此问题。在这个例子中,第三方库为我们提供了一个WithNamespaces定义 的类型t,以及一些注入到我们组件中的其他东西,withNamespaces我们可以将它们用作或与我们的 props 类型定义合并。

 const MyComponent: React.FunctionalComponent<WithNamespaces> = ({children, t}) => ( // ...

现在MyComponent编译并为我可能的道具提供了很好的类型安全性。但是,现在我的测试文件很生气,因为我没有为组件定义期望的 props 提供值,例如t. 然而,我们知道这将被 HOC 注入,所以创建一个 mock 或为这个 prop 提供一些垃圾的值只会令人困惑,而且修复类型问题的额外工作是不必要的。

// type is missing the following properties from WithNamespaces: t, etc., etc.
const wrapper = shallow(<MyComponent>Test</MyComponent>)

我可以通过使我的组件的 props 部分 ala 来捏造它FunctionalComponent<Partial<WithNamespaces>>,但是现在我必须有条件地检查我需要或使用的那些 props t!(非空断言运算符),这些看起来不必要地烦人,融化了 TS 新手的大脑,而且似乎有点臭。

我也可以在我的渲染函数(或在类中,任何访问道具的方法)中投射道具,以向我的消费者隐藏注入的道具:

const MyComponent: React.FunctionalComponent = (props) => {
  const { children, t } = props as WithNamespaces
  return (
    <a title={t('my translated text')}>{children}</a>
  )
}

不过,这有点笨拙和不雅。还有许多其他方法,比如转换为 any 并返回到不引用 WithNamespaces 的东西等,但肯定有更好的方法来做到这一点吗?

杂项

withNamespace确实有一个定义,它使用该Omit模式从返回的类型中排除道具WithNamespaces,但这似乎不起作用,至少对于功能组件。

4

0 回答 0