ReactJS 和 Typecript: 指的是一个值,但在这里被用作类型(TS2749)

我在一个。Tsx 文件。在我的一个自定义组件中,我想创建一个对我在自定义组件中使用的一个组件的引用。

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 >”是不可赋值的 类型’((实例: HTMLDivElement | null) = > void) | 类型 ’RefObject < (props: TextFieldProps) = > Element >’不能赋值给 输入’RefObject’。 Type’(props: TextFieldProps) = > Element’在类型‘ HTMLDivElement’中缺少以下属性: RemoveEventListener、 accKey 和238 more. TS2322

有什么想法吗? 非常感谢

115586 次浏览

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

译者: 在您的情况下,您只需要编写 InstanceType<typeof TextField>而不是 TextField

在 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 泛型为您获取所需的实例类型。

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

.ts文件更改为 .tsx

对我来说很有效

对于将来的查看器,错误也可能是由于您首先没有导入类造成的。

这应该是一个评论,但我没有足够的声誉。 我想与大家分享的是,使用 公认的答案推荐的解决方案的一个简单方法是声明一个具有相同名称(不会引起冲突)的类型别名。然后,您可以按照通常使用实例类型的相同方式使用类型。

再加上一个例子:

import {MyClass} from './myclass';


type MyClass = InstanceType<typeof MyClass>;


let abc: MyClass; // still no error!

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

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

使用 import type方法需要注意的是,不能将其用作值(例如,构造 new MyClass(...))。

我不得不把 heroes: HEROES改成 heroes = HEROES

我在构建一个角度应用程序时遇到了同样的 x refers to a value, but is being used as a type here. Did you mean 'typeof x'?错误。 我花了两个小时寻找补丁,读了好几遍这篇 Stack Overflow 文章。我犯了个小错误。

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

对我来说,错误是由于错误的文件扩展名使用了. ts 而不是. js

对于我来说,也出现了错误,并且将导入从:

import mytype from '../path/file'

import { mytype } from '../path/file'

解决了这个问题。

用关键字 “ typeof”预置数据类型对我来说很有用。

let variable: typeof <data type> = ...

例如:

 let packs: typeof Card[] = await Card.find({ category: cat, rarity: rar });