網站搜尋

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

我解決了很多「not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes'」類型的錯誤(微軟已關閉該問題),方法是聲明一個整個傳遞給組件的對象。

根據原作者的範例,不要使用 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

你所需要做的就是正確聲明元件類型以包含 props 類型:

interface IMyProps {
    myValue: boolean,
}

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

export default MyComponent;

然後你可以這樣使用它:

import MyComponent from '../MyComponent';

...

return <MyComponent myValue={true} />

瞧,TypeScript 現在很高興。好處是 TypeScript 現在會檢查只傳遞 props 介面中實際存在的參數(可以防止拼寫錯誤等等)。

對於標準元件,它會類似於(已經在 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 分別表示組件 SearchBar 預期的 props 類型和 state 類型。當你使用 TypeScript 時,必須給出 propTypes 和 stateType。
你可以使用關鍵字 any 來避免指定類型,但如果你真的想充分利用 TypeScript,我強烈建議你不要走這條“邪惡”的路。就你的情況而言,似乎你沒有指定 state 的類型卻使用了它,修正這一點就能解決這個問題。

編輯 1
在介面 SearchBarProps 中,當我們在 optionalArgument 前加上問號 ? 時,它就變成一個可選參數,因此即使你沒有明確傳遞 optionalArgument,<SearchBar term='some term' /> 也不會顯示任何錯誤。
希望這能解決你的問題!