How to fix property ‘#’ does not exist on type ‘Readonly<{}>‘ in React

Property ‘#’ does not exist on type ‘Readonly<{}>’ error occurs when you have no TypeScript type declarations or similar in it at all. To solve the problem, declare the type for the state or props when passing to the component.

What causes Property ‘#’ does not exist on type ‘Readonly<{}>’ in React?

Suppose we have the following code:

import React from "react";

export default class App extends React.Component {
    constructor(props: any) {
        super(props);
        this.state = { text: "" };
        this.handleInputChange = this.handleInputChange.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
    }

    handleInputChange(e: any) {
        this.setState({ text: e.target.value });
    }

    handleSubmit(e: any) {
        console.log(this.state.text);
        e.preventDefault();
    }

    render() {
        return (
            <form onSubmit={this.handleSubmit}>
                <input
                    type="text"
                    value={this.state.text}
                    onChange={this.handleInputChange}
                />
                <button type="submit">Submit</button>
            </form>
        );
    }
}

The above code will return a form consisting of an input tag and a button.

this.state = { text: "" } : store the value of <input> 

handleSubmit: when you click the Submit button, you will see the string you just entered in the console log.

But when you try to run the application, this error occurs:

Property 'text' does not exist on type 'Readonly<{}>'.ts(2339)

React.Component is a generic interface with two type arguments, both of which have default values: the props received by the component and the state the component maintains. 

class React.Component<P = {}, S = {}, SS = any>

The default state is (no state items at all). 

The main reason is your component has a state this.state = { text: "" }, and you are not declaring a Typescript type for it.

How to fix?

Declare it directly when creating the component

You need to add <{}, {text: string}> to the right side of React.Component. Here the input value is a string, so we will leave text: string

import React from "react";

export default class App extends React.Component<{}, { text: string }>{
    constructor(props: any) {
        super(props);
        this.state = { text: "" };
        this.handleInputChange = this.handleInputChange.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
    }

    handleInputChange(e: any) {
        this.setState({ text: e.target.value });
    }

    handleSubmit(e: any) {
        e.preventDefault();
        console.log(this.state.text);
    }

    render() {
        return (
            <form onSubmit={this.handleSubmit}>
                <input
                    type="text"
                    value={this.state.text}
                    onChange={this.handleInputChange}
                />
                <button type="submit">Submit</button>
            </form>
        );
    }
}

Note that you should also declare the type for the props in the constructor.

Output:

Declare by interface

Interface in typescript allows you to define what properties and methods are needed by the object to be implemented.

We will use it to describe the input parameters as follows:

interface Text {
    text: string;
}

Then set the style to the App component:

export default class App extends React.Component<{}, Text>{
	// ...
}

Output:

Summary

In short, to fix the property ‘#’ does not exist on type ‘Readonly<{}>’ error in React, you can use the method given above to solve the problem. If you have any questions, please leave us a comment.

Leave a Reply

Your email address will not be published. Required fields are marked *