首页 > 解决方案 > React:通过 HOC 注入 props 而不为它们声明类型

问题描述

我正在尝试connect()在 react-redux 绑定中做一些事情。这是我在组件中注入 props 的 HOC:

export function withAdditionalProps<T, I>(
  injectedProps: I,
  WrappedComponent: React.ComponentType<T>,
): React.ComponentType<Omit<T, keyof I>> { ... }

如果我声明注入的 props 类型(I泛型类型),它可以正常工作,但是如果我想做一个 HOC 而不声明这些类型(即时省略注入的 props 键)。如何从传递的道具中确定键?例如,我尝试过这样的事情:

export function withAdditionalProps<T>(
  injectedProps: { [key: string]: unknown },
  WrappedComponent: React.ComponentType<T>,
): React.ComponentType<Omit<T, keyof typeof injectedProps>> { ... }

const InjectedComponent = withAdditionalProps<AppState>(
  {
     counter: 0
  },
  (props) => (<div>{props.counter}</div>)
);

但它不能正常工作:编译器在渲染组件时抛出错误。看截图(testProp 是组件的“本机”道具) 问题 也许任何人都可以帮助我。

标签: reactjstypescript

解决方案


简而言之,您的第二个示例在 Typescript 中是不可能的。

问题是该{ [key:string]: unknown }类型总是将所有可能的字符串作为键捕获,而不是缩小到您在特定调用中使用的具体字符串,这将使Omit这里的使用成为可能。

实际上,Omit使用 with 时会{ [key:string]: unknown }忽略所有可能的键,因此会忽略T. 这可能在未来通过否定类型功能实现,但目前唯一的方法是通过声明类型变量,如您的第一个示例。

但是,函数定义中声明的类型变量并不要求您在每次调用时也声明它们。请参阅下面的代码 - 编译器将在您调用函数时从您传递的具体参数中推断出T两者I。所以在实践中,这里唯一的区别在于你的 HOC 的类型定义,老实说,无论哪种方式,它似乎都具有相似的努力/可读性。

function foo<T, I>(t: T, i: I): Omit<T, keyof I> { 
    return { ...t, ...i }
}

// notice explicitly declaring foo<{ a: number, b: number}, { c: number }> 
// is NOT necessary. The correct types are just inferred from the args you pass.
const bar = foo({ a: 1, b: 2 }, { b: 3 })

bar.a // OK
bar.b // ERROR, since b is omitted

推荐阅读