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

avatar
Borislav Hadzhiev

Last updated: Jan 15, 2023
3 min

banner

# 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 that 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 its 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.

# Using the React.Component generic

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;
The code for this article is available on GitHub

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.

# Disable type checking with the any type

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;
The code for this article is available on GitHub

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;
The code for this article is available on GitHub

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

You can learn more about using TypeScript with React by checking out the following tutorials:

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.

Copyright ยฉ 2024 Borislav Hadzhiev