【问题标题】:React Typescript - Types are incompatible with Thrid Party LibraryReact Typescript - 类型与第三方库不兼容
【发布时间】:2021-10-09 01:26:04
【问题描述】:

我有一个第三方库可以像这样导出 React 组件:

// Code I can not change
export default class MyIcon extends React.Component {
...
};

MyIcon.propTypes = {
  color?: PropTypes.String
}

我正在使用 Typescript,所以我为这个模块做了定义:

// Code I can change
declare module '@thirdparty/MyIcon' {
import React from 'react';

interface Props {
color?: string
}

const Icon: React.FC<Props>;
export default Icon;

现在,有一个 typescript 组件具有这种结构:

// Code I can not change
interface IButton {
icon?: React.Component,
text: string
}

export default const Button: FC<IButton> = ({ icon, text }) => {...}

在我想使用 MyIcon 组件并将其传递给 Button 组件之前,一切正常。我得到的错误是Type React.FC&lt;Props&gt; is incompatible with Component&lt;{}, {}, {}&gt;

我最终这样做了:

&lt;Button icon={myIcon as unknown as Component} /&gt;

但让我感到沮丧的是不知道为什么会失败。

回答

在与第三方库的创建者交谈后,我发现他们将类型设置为组件,因为他们需要在内部进行更改。但是这样做,他们迫使我的另一个第三方库表现得像一个类而不是一个 ReactNode。所以基本上输入图标将适用于第三方库之一,但它不允许我在我的项目中使用另一个第三方库,请参见下面的代码:

// Ok Code
<Button icon={MyIcon}>Works</Button>

// Wrong Code
<div><MyIcon /> Error on Typescript</div> 

显然问题不在于类型,而在于第三方库之一要求图标是组件而不是 ReactNode 的方式。就我而言,这对我来说是一个完整的问题。希望这对某人有所帮助。

【问题讨论】:

  • 你可以直接使用icon: typeOf MyIcon。让我知道这是否有效。
  • 你在哪里使用了模块中定义的Icon可以更改?
  • 这只是类型的声明。所以,我只是想使用 2 个库。一个库是 Icon 库,第二个库是接收 Icon 作为道具的组件。这两个库都是第三方库。

标签: javascript reactjs typescript types


【解决方案1】:

好吧,您使用React.FC 表示Icon,但Icon 是类组件而不是功能组件

试试

const Icon: React.Component<Props>

【讨论】:

  • 它不起作用我一直收到错误消息,我已经尝试过 Component、ComponentType、ComponentClassic。如果我使用那些我得到的错误是'The Expression is not callable'
【解决方案2】:

不需要基于类的组件,您只需键入 icon 即可允许任何节点:

interface IButton {
  icon?: React.Node,
  text: string
}

【讨论】:

  • 是的,我已经尝试过了,而且效果很好,但这意味着要分叉第三方库只是为了更改类型。但问题更多的是为什么 Component 会失败,以及应该如何定义类型以按照最初定义的方式工作。
  • 第三方库可能只是类型错误。我认为这里没有合理的解决方案。
  • 在这一点上,我非常接近于联系图书馆的作者,直接向他询问。问题是我不确定他是否还在公司工作。但经过 2 天的尝试,我的猜测是一样的。他们的类型一定有问题。
  • 我给了你分数,因为确实,问题出在库而不是打字稿问题。
【解决方案3】:

这里你说Icon 的类型是React.FC&lt;Props&gt;

const Icon: React.FC<Props>;

但是您在这里说过您希望iconundefinedReact.Component

icon?: React.Component,

React.FC != React.Component.

将您的代码更改为:

icon?: React.FC<Props>

您可能需要导出该界面:

// icon.tsx

export interface IconProps {
  // types here
}

这样你就可以在外部模块中使用它了。

【讨论】:

  • 我想我的问题并不是很清楚,我只是添加了一些 cmets 来更具体地了解我可以更改的代码
  • 很多人已经把你的问题给你了... React.Component 和 React.FC 不是一回事,要么让它成为一个组件,要么让它成为一个功能组件。不要在你的类型和实际组件之间混淆这两者。
【解决方案4】:

我不确定这个示例是否可行,但您可以尝试像这样更改 typescript 中的类型。

interface X {
    icon: boolean;
}

interface Y extends Omit<X,"icon">{
    icon: string; 
}

【讨论】:

  • 这基本上从 X 创建了一个新接口 Y,省略了 X 中的字段“icon”并使用接口 Y 中定义的字段“icon”。
猜你喜欢
  • 2020-06-30
  • 1970-01-01
  • 2022-01-22
  • 2019-09-06
  • 2019-04-30
  • 2020-12-11
  • 2018-09-10
  • 2019-02-20
  • 2017-03-01
相关资源
最近更新 更多