json - סוג '{}'' אינו ניתן להקצה לסוג 'IntrinsicAttributes & IntrinsicClassAttributes'


אני כרגע יוצר אפליקציית React פשוטה. זהו 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();

והנה יש לי את 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;

וגם מכולת סרגל החיפוש שלי:

    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;

ולבסוף יש לי את 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"
  ]
}

אני ממשיך לקבל שגיאות שונות אחרי שגיאות וכאשר אני מתקן שגיאה אחת מופיעה שגיאה אחרת, אני לא בטוח מה עשיתי שגורם לזה להתנהג כך. זו השגיאה האחרונה:

./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 '{}'.

ניסיתי לתקן את זה על ידי שינוי הקובץ tsconfig.json שלי אבל השגיאה אותה ממשיכה להופיע, מה אני עושה לא נכון ולמה TypeScript מתנהג ככה. אני חדש מאוד בזה ובדוגמה הזו אני מנסה להבין איך React עובד יחד.

תשובה #1

פתרתי הרבה שגיאות מסוג "לא ניתן להקצות לסוג 'IntrinsicAttributes & IntrinsicClassAttributes'" (מיקרוסופט סגרה את הבעיה) פשוט על ידי הכרזת אובייקט שמעבירים אותו בשלמותו לרכיב.

עם הדוגמה של OP, במקום להשתמש ב-term={this.props.term}, השתמש ב-{...searchBarProps} כדי שזה יעבוד:

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>
  );
}

תשובה #2

כל מה שאתה צריך לעשות הוא להכריז על סוג הרכיב כראוי כדי לכלול את סוג התכונות:

interface IMyProps {
    myValue: boolean,
}

const MyComponent: React.FC<IMyProps> = (props: IMyProps) => {
    ...
}

export default MyComponent;

אז אתה יכול להשתמש בזה כ:

import MyComponent from '../MyComponent';

...

return <MyComponent myValue={true} />

והנה, טייפסקריפט שמח. הדבר הטוב בזה הוא שטייפסקריפט עכשיו בודק שהמעבירים פרמטרים קיימים באמת בממשק הפרופס (יכול למנוע שגיאות כתיב וכדומה).

לרכיב הסטנדרטי זה יהיה משהו דומה ל(מה שכבר נמצא בדוגמה של Swapnill):

class MyComponent extends React.Component<IMyProps, IMyState>{
    constructor(props: IMyProps){}
}
export default MyComponent;

תשובה #3

הבעיה כאן אינה בהגדרות tslint שלך. הסתכל על קטע הקוד הבא:

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>
    )
  }
}

ב־class SearchBar extends React.Component<SearchBarProps, SearchBarState> {, SearchBarProps ו־SearchBarState מציינים את סוג ה־props הצפויים ואת סוג ה־state עבור הרכיב SearchBar בהתאמה. עליך לתת propTypes ו־stateType כשאתה משתמש ב־TypeScript.
ניתן להימנע מלספק סוגים על ידי שימוש במילת המפתח any, אך אני מאוד ממליץ שלא ללכת בדרך זו אם אתה באמת רוצה לנצל את השימוש ב־TypeScript. במקרה שלך נראה שטרם ציינת את סוג ה־state ושימוש בו, תיקון זה יפתור את הבעיה.

עריכה 1
בממשק SearchBarProps, optionalArgument הופך לפרמטר אופציונלי כאשר מוסיפים לו סימן שאלה ? לפניו, כך ש-<SearchBar term='some term' /> לא יראה שום שגיאה גם אם לא תעביר את optionalArgument במפורש.
מקווה שזה פותר את הבעיה שלך!