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

avatar

Borislav Hadzhiev

Last updated: Mar 22, 2022

banner

Photo from Unsplash

React: Property 'X' does not exist on type 'Readonly<{}>' #

The React.js error "Property does not exist on type 'Readonly<{}>'" occurs when we try to access the props or state of a class component which we haven't typed. To solve the error, use the generic on the React.Component class to type the props or state objects of the class.

property value does not exist on type readonly

Here is an example of how the error occurs.

App.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;

Notice that our class component has a value property in it's state object.

The cause of the error is - we haven't typed the state object of the class, so if we try to access any property on the state object, we would get an error.

The same is the case for the props object - trying to access a property on the props object would cause an error if we don't explicitly type it.

To solve the error, use the generic of the React.Component class as React.Component<PropsObject, StateObject>.

App.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;

We typed the value property on the state object in the class, so we are now able to access it as this.state.value.

We passed an empty object for the type of the props object because this class doesn't take any props.

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.

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" />.

Conclusion #

To solve the React.js error "Property does not exist on type 'Readonly<{}>'", make sure to explicitly type the props or state object of the class, adding any of the properties you intend to access on the props or state objects.

I wrote a book in which I share everything I know about how to become a better, more efficient programmer.
book cover
You can use the search field on my Home Page to filter through all of my articles.