ReactJS 和 Typescript:指的是一个值,但在这里用作类型 (TS2749)
ReactJS and Typescript : refers to a value, but is being used as a type here (TS2749)
我正在用 Typescript 和 Material-ui 在 .tsx 文件中编写 ReactJS class。在我的自定义组件之一中,我想创建对我在自定义组件中使用的组件之一的引用。
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' refers to a value, but is being used as a type here. TS2749
我试图将 "typeof TextField" 放入我的声明中,但我收到另一条消息,当 valuing 在我的渲染中引用 属性 时:
Type 'RefObject<(props: TextFieldProps) => Element>' is not assignable
to type '((instance: HTMLDivElement | null) => void) |
RefObject | null | undefined'. Type
'RefObject<(props: TextFieldProps) => Element>' is not assignable to
type 'RefObject'.
Type '(props: TextFieldProps) => Element' is missing the following properties from type 'HTMLDivElement': align, addEventListener,
removeEventListener, accessKey, and 238 more. TS2322
有什么想法吗?
非常感谢
所以我 运行 之前在我的代码中多次遇到这个问题,但直到今天才弄清楚发生这种情况的原因。
TL;最后的 DR 是问题的实际答案。
当您在 TypeScript 中创建一个 class 时,该 class 的名称指的是实例类型和 Javascript class 值。如果您将 class 作为类型引用,TypeScript 会自动将其检测为 class 的实例类型。如果您在运行时引用 class,它只是按照 Javascript 的含义使用它。到现在为止一切都很好。
class MyClass {}
let abc: MyClass; // ts recognizes as instance type
abc = new MyClass(); // completely fine, used here as the javascript value
但是,真正的问题是当您从模块 动态 导出 class 时。当你以某些方式导出 class 时,TypeScript 只能导出 class 的 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 运算符为 class 值获取 class 构造函数类型,InstanceType 泛型获取所需的实例类型。
长话短说:
在你的情况下,你只需要写 InstanceType<typeof TextField>
而不是 TextField
.
确保你在 .tsx
文件而不是 .ts
文件
将 .ts
文件更改为 .tsx
在我的情况下有效
对于未来的观众,错误也可能是由于您没有首先导入 class。
这应该是一个评论,但我没有足够的声誉。
我想分享一种使用 is to declare a type alias with the same name ( 推荐的解决方案的简洁方法。然后您可以像通常使用实例类型一样使用您的类型。
添加示例:
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
。
我 运行 在构建 Angular 应用程序时遇到同样的 x refers to a value, but is being used as a type here. Did you mean 'typeof x'?
错误。
我花了两个小时寻找修复程序,多次阅读 Stack Overflow post。我的简单错误。
要检查的另一件事是您正在执行的导入是否被 {}
包围。出现此消息的原因之一是因为任何未被 {}
包围的内容都被视为文件的默认导出。
我正在用 Typescript 和 Material-ui 在 .tsx 文件中编写 ReactJS class。在我的自定义组件之一中,我想创建对我在自定义组件中使用的组件之一的引用。
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' refers to a value, but is being used as a type here. TS2749
我试图将 "typeof TextField" 放入我的声明中,但我收到另一条消息,当 valuing 在我的渲染中引用 属性 时:
Type 'RefObject<(props: TextFieldProps) => Element>' is not assignable to type '((instance: HTMLDivElement | null) => void) | RefObject | null | undefined'. Type 'RefObject<(props: TextFieldProps) => Element>' is not assignable to type 'RefObject'. Type '(props: TextFieldProps) => Element' is missing the following properties from type 'HTMLDivElement': align, addEventListener, removeEventListener, accessKey, and 238 more. TS2322
有什么想法吗? 非常感谢
所以我 运行 之前在我的代码中多次遇到这个问题,但直到今天才弄清楚发生这种情况的原因。
TL;最后的 DR 是问题的实际答案。
当您在 TypeScript 中创建一个 class 时,该 class 的名称指的是实例类型和 Javascript class 值。如果您将 class 作为类型引用,TypeScript 会自动将其检测为 class 的实例类型。如果您在运行时引用 class,它只是按照 Javascript 的含义使用它。到现在为止一切都很好。
class MyClass {}
let abc: MyClass; // ts recognizes as instance type
abc = new MyClass(); // completely fine, used here as the javascript value
但是,真正的问题是当您从模块 动态 导出 class 时。当你以某些方式导出 class 时,TypeScript 只能导出 class 的 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 运算符为 class 值获取 class 构造函数类型,InstanceType 泛型获取所需的实例类型。
长话短说:
在你的情况下,你只需要写 InstanceType<typeof TextField>
而不是 TextField
.
确保你在 .tsx
文件而不是 .ts
文件
将 .ts
文件更改为 .tsx
在我的情况下有效
对于未来的观众,错误也可能是由于您没有首先导入 class。
这应该是一个评论,但我没有足够的声誉。
我想分享一种使用
添加示例:
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
。
我 运行 在构建 Angular 应用程序时遇到同样的 x refers to a value, but is being used as a type here. Did you mean 'typeof x'?
错误。
我花了两个小时寻找修复程序,多次阅读 Stack Overflow post。我的简单错误。
要检查的另一件事是您正在执行的导入是否被 {}
包围。出现此消息的原因之一是因为任何未被 {}
包围的内容都被视为文件的默认导出。