首页 > 解决方案 > ts:“道具”可以用与另一种类型无关的任意类型实例化

问题描述

const withFirebase = <Props extends {firebase: Firebase}>(
  Component: React.ComponentType<Props>
): ComponentType<Omit<Props, "firebase">> => (props) => (
  <FirebaseContext.Consumer>
    {(firebase) => <Component {...props} firebase={firebase} />}
  </FirebaseContext.Consumer>
);

export default withFirebase;

这里

<Component {...props} firebase={firebase} />

引发以下打字稿错误

Type 'Pick<Props, Exclude<keyof Props, "firebase">> & { firebase: Firebase | null; children?: ReactNode; }' is not assignable to type 'IntrinsicAttributes & Props & { children?: ReactNode; }'.
  Type 'Pick<Props, Exclude<keyof Props, "firebase">> & { firebase: Firebase | null; children?: ReactNode; }' is not assignable to type 'Props'.
    'Props' could be instantiated with an arbitrary type which could be unrelated to 'Pick<Props, Exclude<keyof Props, "firebase">> & { firebase: Firebase | null; children?: ReactNode; }

添加了 Omit<Props, "firebase"> 以避免 Wrapped 组件导入中所需的 prop 错误。

喜欢

const App = () => {
  return (
    <ItemWithFirebase /> // If not omit is available this will throw prop firebase not available error
  )
}

const Item: FC<{firebase: Firebase}> = ({firebase}) => {
...
}

const ItemWithFirebase = withFirebase(Item);

我已经投下了传播道具如下

<Component {...(props as Props)} firebase={firebase} />}

但我不确定我是否做得对。您能否让我知道是否有其他方法可以解决此错误?

标签: reactjstypescriptfirebase

解决方案


这在编写 HOC 时总是会出现。您正在查看错误,它显示“我们获取Props,我们删除Props['firebase'],我们添加{firebase: Firebase | null},并且我们不确定这个对象是否可以分配给Props”。您可能会想,“如果我删除firebase然后添加它,那当然是同一件事”。 从技术上讲Props extends {firebase: Firebase}这意味着它Props['firebase']可能比 更具体Firebase,在这种情况下,您提供给它的值是不够的。这种奇怪的边缘情况是您收到错误的两个原因之一。

另一个原因是Props不允许 for firebaseto be null,但 theConsumer说它可以有Firebaseor null

但是 99.9% 的时间它是同一件事,所以可以{...(props as Props)}像你在这里所做的那样断言。您可能希望扩展Props为 allow null,但如果您知道它不会出现null在您的应用程序中,那么这不是问题。

如果你让你的泛型Props代表没有firebase. 我们没有从返回中删除firebase,而是将其添加到Component. 我们Omit任何现有的定义都firebase排除Props了边缘情况,即Component需要某些值而firebase不是我们提供的值。

const withFirebase = <Props extends {}>(
  Component: React.ComponentType<Omit<Props, 'firebase'> & {firebase: Firebase | null}>
): ComponentType<Props> => (props) => (
  <FirebaseContext.Consumer>
    {(firebase) => <Component {...props} firebase={firebase} />}
  </FirebaseContext.Consumer>
);

推荐阅读