反应:属性“X”在类型“只读”上不存在

React: 类型 ‘Readonly<{}>’ 上不存在属性 ‘X’

React: Property ‘X’ does not exist on type ‘Readonly<{}>’

React.js 错误“Property does not exist on type ‘Readonly<{}>’”发生在我们尝试访问我们没有键入的类组件的属性或状态时。

要解决该错误,请使用类上的泛型React.Component来键入类的道具或状态对象。

只读类型不存在属性值

下面是错误如何发生的示例。

应用程序.tsx
import React from 'react'; class App extends React.Component { constructor(props: any) { super(props); this.state = {value: ''}; // 👈️ uses state but we haven't typed it } handleChange = (event: any) => { this.setState({value: event.target.value}); }; render() { return ( <div> <form> {/* ⛔️ Error: Property 'value' does not exist on type 'Readonly<{}>'.ts(2339) */} <input onChange={this.handleChange} type="text" value={this.state.value} /> <button type="submit">Submit</button> </form> </div> ); } } export default App;

请注意,我们的类组件value在其状态对象中有一个属性。

错误的原因是——我们没有输入类的状态对象,所以如果我们试图访问状态对象的任何属性,我们会得到一个错误。

对象的情况也是如此props——如果我们不显式地键入它,试图访问 props 对象的属性将导致错误。

使用 React.Component 泛型

要解决该错误,请使用类的泛型React.Componentas
React.Component<PropsObject, StateObject>

应用程序.tsx
import React from 'react'; // 👇️ we set the props to empty object, and set the state to {value: string} class App extends React.Component<{}, {value: string}> { constructor(props: any) { super(props); this.state = {value: ''}; } handleChange = (event: any) => { this.setState({value: event.target.value}); }; render() { return ( <div> <form> <input onChange={this.handleChange} type="text" // ✅ Everything works now value={this.state.value} /> <button type="submit">Submit</button> </form> </div> ); } } export default App;

我们在类中键入了对象value的属性state,因此我们现在可以将其作为this.state.value.

我们为道具对象的类型传递了一个空对象,因为此类不接受任何道具。

any禁用类型检查

If you don’t know how to type the props or state objects and want to disable
type checking, use the any type.

App.tsx
import React from 'react'; // 👇️ type checking disabled for props and state class App extends React.Component<any, any> { constructor(props: any) { super(props); this.state = {value: ''}; } handleChange = (event: any) => { this.setState({value: event.target.value}); }; render() { return ( <div> <form> <input onChange={this.handleChange} type="text" value={this.state.value} /> <button type="submit">Submit</button> </form> </div> ); } } export default App;

We used the any type when typing the props and state objects, which
effectively turns off type checking.

Now you would be able to access any property on the this.props and this.state objects without getting a type checking error.

# Explicitly type a props object

Here is an example of a class that also explicitly types the props object.

App.tsx
import React from 'react'; // 👇️ type props as {name: string}, and state as {value: string} class App extends React.Component<{name: string}, {value: string}> { constructor(props: any) { super(props); this.state = {value: ''}; } handleChange = (event: any) => { this.setState({value: event.target.value}); }; render() { return ( <div> <form> <input onChange={this.handleChange} type="text" value={this.state.value} /> <button type="submit">Submit</button> </form> <h1>{this.props.name}</h1> </div> ); } } export default App;

We explicitly typed the props object of the App component to have a name
property of type string. Now when you use the component, you would have to
provide the name prop, e.g. <App name="James Doe" />.

# Additional Resources

您可以通过查看以下教程了解有关将 TypeScript 与 React 结合使用的更多信息: