ReactJS 和 Typescript :引用一个值,但在此处用作类型 (TS2749)

新手上路,请多包涵

我在 .tsx 文件中使用 Typescript 和 Material-ui 编写 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 属性时,我还有另一条消息:

类型 ‘RefObject<(props: TextFieldProps) => Element>’ 不可分配给类型 ‘((instance: HTMLDivElement | null) => void) |参考对象 |空 |不明确的’。类型 ‘RefObject<(props: TextFieldProps) => Element>’ 不可分配给类型 ‘RefObject’。类型 ‘(props: TextFieldProps) => Element’ 缺少来自类型 ‘HTMLDivElement’ 的以下属性:align、addEventListener、removeEventListener、accessKey 等 238 个。 TS2322

有任何想法吗 ?太感谢了

原文由 Answerrer 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 5k
2 个回答

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

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<typeof TextField> 而不是 TextField

原文由 Mehmet Efe Akça 发布,翻译遵循 CC BY-SA 4.0 许可协议

确保你在 .tsx 文件而不是 .ts 文件

原文由 jonyB 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进