Type '{}' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes

i am currently making a simple react application. this is my index.tsx

import * as React from 'react';
import * as ReactDOM from 'react-dom';
import App from './components/App';
import registerServiceWorker from './registerServiceWorker';

ReactDOM.render(
  <App />,
  document.getElementById('root') as HTMLElement
);
registerServiceWorker();

and here I have my app.tsx

    import * as React from 'react';
import SearchBar from '../containers/price_search_bar';

interface Props {
  term: string;
}

class App extends React.Component<Props> {

  // tslint:disable-next-line:typedef
  constructor(props) {
    super(props);
    this.state = {term: '' };
  }

  render() {
    return (
      <div className="App">
        <div className="App-header">
          <h2>Welcome to React</h2>
        </div>
        <p className="App-intro">
          this is my application.
        </p>
        <div>
            <form>
            <SearchBar term={this.props.term} />
            </form>
        </div>
      </div>
    );
  }
}

export default App;

and also my search bar container:

    import * as React from 'react';

interface Props {
    term: string;
}

// tslint:disable-next-line:no-any
class SearchBar extends  React.Component<Props> {

    // tslint:disable-next-line:typedef
    constructor(props) {
        super(props);
        this.state = { term: '' };
    }

    public render() {
        return(
            <form>
                <input 
                    placeholder="search for base budget"
                    className="form-control"
                    value={this.props.term}
                />
                <span className="input-group-btn" >
                    <button type="submit" className="btn btn-secondary" >
                        Submit
                    </button>
                </span>

            </form>
        );
    }
}

export default SearchBar;

and finally I have my tsconfig.json:

{
  "compilerOptions": {
    "outDir": "build/dist",
    "module": "esnext",
    "target": "es5",
    "lib": ["es6", "dom"],
    "sourceMap": true,
    "allowJs": true,
    "jsx": "react",
    "moduleResolution": "node",
    "rootDir": "src",
    "forceConsistentCasingInFileNames": true,
    "noImplicitReturns": true,
    "noImplicitThis": true,
    "noImplicitAny": false,
    "strictNullChecks": true,
    "suppressImplicitAnyIndexErrors": true,
    "typeRoots": [
      "node_modules/@types"
    ],
    "noUnusedLocals": true
  },
  "exclude": [
    "node_modules",
    "build",
    "scripts",
    "acceptance-tests",
    "webpack",
    "jest",
    "src/setupTests.ts"
  ]
}

I keep getting different errors after errors and when ever I fix one error another one appears, I am not sure what I have done that make it behave like this. This is the latest error:

./src/index.tsx
(7,3): error TS2322: Type '{}' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<App> & Readonly<{ children?: ReactNode; }> & Reado...'.
  Type '{}' is not assignable to type 'Readonly<Props>'.
    Property 'term' is missing in type '{}'.

I tried to fix it by modifying my tsconfig.json but the same error still appears, what am I doing wrong and why typescript is bahing like this. I am very new to this and by this example I am trying to udnertand how react works all together.


Solution 1:

I solved a lot of "not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes" type of errors (Microsoft closed issue) just by declaring an object that is passed entirely to the component.

With the OP's example, instead of using term={this.props.term}, use {...searchBarProps} to get it working:

render() {
  const searchBarProps = { // make sure all required component's inputs/Props keys&types match
    term: this.props.term
  }
  return (
    <div className="App">
      ...
      <div>
          <form>
          <SearchBar {...searchBarProps} />
          </form>
      </div>
    </div>
  );
}

Solution 2:

The problem here is not with your tslint settings. Look at the following code snippet:

interface SearchBarProps {
  term: string;
  optionalArgument?: string;
}

interface SearchBarState{
  something: number;
}

class SearchBar extends React.Component<SearchBarProps, SearchBarState> {
  constructor(props: SearchBarProps){
    super(props);

    this.state = {
      something: 23
    };
  }

  render() {
    const {something} = this.state;
    return (
      <div>{something}</div>
    )
  }
}

In class SearchBar extends React.Component<SearchBarProps, SearchBarState> {, SearchBarProps and SearchBarState denote type of expected props and type of state for component SearchBar respectively. You must give propTypes and stateType when you use typescript.
You can avoid giving types by using keyword any but I highly suggest you not to follow this "evil" path if you truly want to take advantage of using typescript. In your case it seems that you haven't specified type of state and used it, fixing that will solve this problem.

Edit 1
In interface SearchBarProps, optionalArgument becomes an optional argument as we add a question mark ? in front of it, so <SearchBar term='some term' /> won't show any error even if you don't pass optionalArgument explicitly.
Hope this solves your problem!