Ans*_*rer 31 validation typescript reactjs material-ui tsx
我在 .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;
}
}
Run Code Online (Sandbox Code Playgroud)
在编译期间,我在引用的声明中收到错误消息:
'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
有任何想法吗 ?太感谢了
Meh*_*kça 29
所以我之前在我的代码中多次遇到过这个问题,但直到今天才弄清楚发生这种情况的原因。
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
Run Code Online (Sandbox Code Playgroud)
但是,真正的问题是当您从模块动态导出类时。当你以某种方式导出类时,TypeScript 只能导出类的 Javascript 值,不会导出类型。因此,如果您将其导入另一个模块并尝试将其作为类型引用,您将获得 TS2749。
let intervariable = class MyClass{}
export const MyClass = intervariable; // TypeScript does not export type here.
Run Code Online (Sandbox Code Playgroud)
import {MyClass} from './myclass';
let abc: MyClass; // TypeScript error TS2749
Run Code Online (Sandbox Code Playgroud)
发生这种情况时,尤其是在您无法控制的情况下,我获取实例类型的解决方案只是使用 InstanceType 和 typeof:
import {MyClass} from './myclass';
let abc: InstanceType<typeof MyClass>; // no error
// the rest...
Run Code Online (Sandbox Code Playgroud)
typeof 运算符为您提供类值的类构造函数类型,InstanceType 泛型为您提供所需的实例类型。
TL;DR:在你的情况下,你只需要写InstanceType<typeof TextField>
而不是TextField
.
Ini*_*asP 11
这应该是一个评论,但我没有足够的声誉。我想分享的是,使用已接受答案推荐的解决方案的一种干净方法是声明具有相同名称的类型别名(它不会导致冲突)。然后,您可以像通常使用实例类型一样使用您的类型。
添加到示例:
import {MyClass} from './myclass';
type MyClass = InstanceType<typeof MyClass>;
let abc: MyClass; // still no error!
Run Code Online (Sandbox Code Playgroud)
编辑:类型导入似乎也可以工作,而且看起来更干净:
import type {MyClass} from './myclass';
Run Code Online (Sandbox Code Playgroud)
该方法的警告import type
是您不能将其用作值(例如构造new MyClass(...)
)。
归档时间: |
|
查看次数: |
22582 次 |
最近记录: |