ReactJS 和 Typescript :引用一个值,但在此处用作类型 (TS2749)
Posted
技术标签:
【中文标题】ReactJS 和 Typescript :引用一个值,但在此处用作类型 (TS2749)【英文标题】:ReactJS and Typescript : refers to a value, but is being used as a type here (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
有什么想法吗? 非常感谢
【问题讨论】:
可能与***.com/questions/46703364/…相关 我遇到了同样的问题,这很有效! ***.com/a/65332778/11025497 【参考方案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
文件
【讨论】:
这是人们应该检查的第一件事。 有一个类似的问题同样的答案***.com/questions/58341545/…【参考方案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<typeof TextField>
而不是 TextField
。
【讨论】:
我花了太多时间研究这个...谢谢。另一个见解是,Jest 管道与生产/开发管道完全不同...... 是的,由于某种原因,TS 文档中没有正确解释这一点。我的团队在使用一些非 TS 库处理 TS-React 项目时多次遇到此问题。我花了一段时间才弄清楚这一点。以上是关于ReactJS 和 Typescript :引用一个值,但在此处用作类型 (TS2749)的主要内容,如果未能解决你的问题,请参考以下文章
TypeError:fs.existsSync 不是函数(Electron/ReactJS/Typescript)
typesafe 使用 reactjs 和 typescript 选择 onChange 事件
ReactJs 和 Typescript,使用 TSX 时如何更改对象内变量的状态