【问题标题】:ReactJS and Typescript : refers to a value, but is being used as a type here (TS2749)ReactJS 和 Typescript :引用一个值,但在此处用作类型 (TS2749)
【发布时间】:2020-09-15 10:56:29
【问题描述】:

我正在使用 Typescript 和 Material-ui 在 .tsx 文件中编写一个 ReactJS 类。在我的一个自定义组件中,我想创建一个对我在我的自定义组件中使用的组件之一的引用。

export class MyTextField extends React.Component<MyProps, MyState> {
  private refTextField: React.RefObject<TextField>;
  constructor(props: MyProps) {
    super(props);
    this.refTextField = React.createRef();
  }

  render(): JSX.Element {
    const { id, label, value: defaultValue } = this.props;
    const { value } = this.state;
    const element = (
      <TextField ref={this.refTextField} id={id} label={label} defaultValue={defaultValue} value={value} />
    );

    return element;
  }
}

在编译期间,我的引用声明出现错误:

'TextField' 指的是一个值,但在这里被用作一个类型。 TS2749

我试图在我的声明中添加“typeof TextField”,但在我的渲染中评估 ref 属性时,我收到了另一条消息:

Type 'RefObject Element>' 不可赋值 输入 '((实例:HTMLDivElement | null) => void) | 参考对象 |空 |不明确的'。类型 'RefObject Element>' 不可分配给 键入“参考对象”。 类型 '(props: TextFieldProps) => Element' 缺少来自类型 'HTMLDivElement' 的以下属性:align、addEventListener、 removeEventListener、accessKey 等 238 个。 TS2322

有什么想法吗? 非常感谢

【问题讨论】:

标签: reactjs typescript validation material-ui tsx


【解决方案1】:

这应该是评论,但我没有足够的声誉。 我想分享一个使用the accepted answer 推荐的解决方案的干净方法是声明一个具有相同名称的类型别名(it does not cause a conflict)。然后,您可以像通常使用实例类型一样使用您的类型。

添加到示例中:

import {MyClass} from './myclass';

type MyClass = InstanceType<typeof MyClass>;

let abc: MyClass; // still no error!

编辑:类型导入似乎也能正常工作,而且看起来更简洁:

import type {MyClass} from './myclass';

import type 方法的注意事项是您不能将其用作值(例如构造 new MyClass(...))。

【讨论】:

    【解决方案2】:

    .ts 文件更改为.tsx

    在我的情况下它有效

    【讨论】:

    • 这应该放在顶部。拯救了我的一天。
    • 太棒了!在一行中节省了我的一天
    【解决方案3】:

    确保您使用的是.tsx 文件而不是.ts 文件

    【讨论】:

    【解决方案4】:

    要检查的另一件事是您正在执行的导入是否被 {} 包围。出现此消息的原因之一是没有被{} 包围的任何内容都被视为文件的默认导出。

    【讨论】:

      【解决方案5】:

      我不得不将heroes: HEROES 更改为heroes = HEROES

      我在构建 Angular 应用程序时遇到了同样的 x refers to a value, but is being used as a type here. Did you mean 'typeof x'? 错误。 我花了两个小时寻找修复程序,多次阅读这篇 Stack Overflow 帖子。我犯了一个简单的错误。

      【讨论】:

        【解决方案6】:

        对于未来的查看者,错误也可能是由于您没有首先导入该类。

        【讨论】:

          【解决方案7】:

          所以我之前在我的代码中多次遇到这个问题,但今天才弄清楚发生这种情况的原因。

          TL;DR 在最后以获得问题的实际答案。

          当您在 TypeScript 中创建一个类时,该类的名称指的是实例类型和 Javascript 类值。如果您将该类作为类型引用,TypeScript 会自动将其检测为该类的实例类型。如果您在运行时引用该类,它只会按照 Javascript 的含义使用它。到目前为止,一切都很好。

          class MyClass {}
          let abc: MyClass; // ts recognizes as instance type
          abc = new MyClass(); // completely fine, used here as the javascript value
          

          然而,真正的问题是当您从模块中导出类时动态。当你以某种方式导出类时,TypeScript 只能导出类的 Javascript 值,而不能导出类​​型。因此,如果您将其导入另一个模块并尝试将其作为类型引用,您将获得 TS2749。

          let intervariable = class MyClass{}
          export const MyClass = intervariable; // TypeScript does not export type here.
          
          import {MyClass} from './myclass';
          
          let abc: MyClass; // TypeScript error TS2749
          

          当这种情况发生时,尤其是在你无法控制的情况下,我获取实例类型的解决方案是简单地使用 InstanceType 和 typeof:

          import {MyClass} from './myclass';
          
          let abc: InstanceType<typeof MyClass>; // no error
          // the rest...
          

          typeof 运算符为您提供类值的类构造函数类型,而 InstanceType 泛型为您提供所需的实例类型。

          TL;DR: 在你的情况下,你只需要写 InstanceType&lt;typeof TextField&gt; 而不是 TextField

          【讨论】:

          • 我花了太多时间研究这个...谢谢。另一个见解是,Jest 管道与生产/开发管道完全不同......
          • 是的,由于某种原因,TS 文档中没有正确解释这一点。我的团队在使用一些非 TS 库处理 TS-React 项目时多次遇到此问题。我花了一段时间才弄清楚这一点。
          猜你喜欢
          • 2018-08-07
          • 2020-04-28
          • 2021-08-23
          • 2020-12-05
          • 2018-03-31
          • 1970-01-01
          • 2023-04-03
          • 2023-04-05
          • 1970-01-01
          相关资源
          最近更新 更多