Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TS2339: Property 'props' does not exist on type 'Home'

I have a very basic program of react with tsx, I am getting an error which I am not able to figure out why

import React from 'react';
// import {connect} from 'react-redux'

export class Home extends React.Component {    
    render(){
        console.log(this.props)
        return (
            <div>Working</div>
        )
    }
}


import * as React from 'react'
import * as ReactDOM from 'react-dom';
import {Home} from './Components/Home.component'
class App extends React.Component<any,any>{
render(){
    return(
        <Home value="abc" />
    )
  }
}
ReactDOM.render( <App />, window.document.getElementById("app"))

git clone this for code

like image 698
Mukesh Kumar Avatar asked Nov 20 '17 08:11

Mukesh Kumar


1 Answers

Typescript needs to know the shape of the props and state passed to a component. If you really want to stop Typescript from enforcing typings in your component (which, btw, defeats the whole purpose of using Typescript), then, the component that needs access to the props or state passed to it has to specify the type or shape so to speak, as any. That is, your component will look something like this

export class Home extends React.Component<any, any>

instead of

export class Home extends React.Component

which btw, is an incorrect way of extending a class if that class expects props and/or state.

Passing any type for props and state means that the component in question must accept any kind of shape (type) for both props and state.

Try this

import * as React from "react";
import * as ReactDOM from 'react-dom';

export class Home extends React.Component<any, any> {
  render() {
    console.log(this.props)
    return (
      <div>Working</div>
    )
  }
}

class App extends React.Component{
  render() {
    return (
      <Home value="abc" />
    )
  }
}

ReactDOM.render(<App />, document.getElementById("app"));

and everything should work as expected because you got Typescript out of your way in terms of type-checking for you.

You can also view the demo here

If you actually wanted to enforce the shape (type) of the props and/or state you would then have to define these shapes with, usually, an interface or inline type annotation. Here is an example of the same code above that enforces the shape of the props using the former method:

import * as React from "react";
import { render } from "react-dom";

interface Props {
  value:string,
  name:string
}

export default class Home extends React.Component<Props>{
  render() {
    console.log(this.props)
    return (
      <div>Working. The props values are: {this.props.value} {this.props.name}</div>
    )
  }
}

class App extends React.Component {
  render() {
    return (
      <Home value="abc" name="def"/>
    )
  }
}

render(<App />, document.getElementById("root"));

Now, here you could never be able to add any other prop to the Home component that is not defined in the Props interface. For example doing something like:

<Home value="abc" name="DEF" somethin="else"/>

would not compile because somethin is not defined in the interface that is used by the Home component.

To enforce the shape of the state you'd have to do the same thing as for the props, i.e. define a contract (interface). Also, note that you still need to access your props via this NOT Props as this is just a type definition of the structure not holder of the values themselves.

You can view the demo for this alternative here

like image 115
Siya Mzam Avatar answered Oct 19 '22 15:10

Siya Mzam