ts:“道具”可以用与另一种类型无关的任意类型实例化

Posted

技术标签:

【中文标题】ts:“道具”可以用与另一种类型无关的任意类型实例化【英文标题】:ts: 'Props' could be instantiated with an arbitrary type which could be unrelated to another type 【发布时间】:2021-05-11 08:27:33 【问题描述】:
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; 

省略 是为了避免 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 />

但我不确定我是否做得对。能否请您告诉我是否有任何其他方法可以解决此错误?

【问题讨论】:

【参考方案1】:

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

另一个原因是Props 不允许firebasenull,但Consumer 表示它可以有Firebasenull

但 99.9% 的情况下它是同一件事,因此可以像您在此处所做的那样断言 ...(props as Props)。您可能希望扩展 Props 以允许 null,但如果您知道在您的应用中它不会是 null,那么这不是问题。

如果你让你的通用Props 代表没有firebase 的道具,你可以避免一些错误。我们没有从返回中删除firebase,而是将其添加到Component。我们从PropsOmit 任何现有的firebase 定义排除了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>
);

【讨论】:

谢谢@LindaPaiste。这肯定解决了我的错误。它告诉我哪里出错了,我使用了你提供的方法。我从组件中删除了 firebase。

以上是关于ts:“道具”可以用与另一种类型无关的任意类型实例化的主要内容,如果未能解决你的问题,请参考以下文章

TS2339:“家”类型上不存在属性“道具”

创建另一种类型的 htmlhelper 实例

Ts高级类型(Utility Types)

Typescript + Svelte - 如何添加类型以传播组件道具

Vue:无效的道具:类型

Vue 在编译时使用 Typescript 类型检查道具