与打字稿反应:类型不匹配

React with Typescript: Type missmatch

有一段时间开始将 React 与打字稿一起使用,但总是对类型和 React 元素的期望感到困惑。

就像在这种情况下一样(也 sandbox here)我收到 Todos 组件的以下错误

in VSCODE with prettier and TSLint setup: Type '(props: PropsWithChildren) => Element[]' is not assignable to type 'FunctionComponent'.

in Snadbox: Type '(props: IProps) => void[]' is not assignable to type 'FunctionComponent'.


    import { TodoStore } from "./stores/TodoStore";
    import { observable } from "mobx";
    interface IProps {
      todoStore: TodoStore;
    }
   // red underline at `TodoComp` with mentioned error message
    const TodosComp: React.FC<IProps> = props => {
      const { todos } = props.todoStore;
      return todos.map(todo => {
        <div key={todo.id}>
          <p>{todo.title}</p>
          <select />
        </div>;
      });
    };
    export default inject("todoStore")(observer(TodosComp));

待办事项的 Mobx 存储就像

import { decorate, observable, runInAction, action } from 'mobx';
export interface ITodo {userId: number; id: number; title: string; completed: boolean;
}
export class TodoStore {
  public todos: ITodo[];
  constructor() {
    this.todos = [];
    this.fetchTodos();
  }

  public async fetchTodos() {
    const response = await fetch('http://jsonplaceholder.typicode.com/todos');
    const todos: ITodo[] = await response.json();
    runInAction(() => {
      this.todos = todos;
    });
 }}
decorate<TodoStore>(TodoStore, { todos: observable, fetchTodos: action });

是 Mobx 的问题吗,如果 class 本身用作组件中的类型? mobx classes 需要一个单独的接口吗?

另外,作为一个 Mobx 特定问题,沙箱中在提供商处实例化商店 class 的方式是否正确?

一般来说,如果有人知道一篇关于 React with typescript how to manage props and JSX types 的好文章,我们将不胜感激。

函数应该 return 一个 JSX.Element 并且你需要传递一个 div 或一个片段,这应该有效。

const Todos: React.FC<IProps> = (props: IProps): JSX.Element => {
  const { todos } = props.todoStore;
  return (<React.Fragment>
    {todos.map(todo => {
      <div key={todo.id}>
        <p>{todo.title}</p>
        <select />
      </div>;
    })}
  </React.Fragment>);
};

FunctionComponent 定义为

interface FunctionComponent<P = {}> {
  (props: PropsWithChildren<P>, context?: any): ReactElement | null;
  ...

其中 ReactElement

interface ReactElement<P = any, T extends string | JSXElementConstructor<any> = string | JSXElementConstructor<any>> {
  type: T;
  props: P;
  key: Key | null;
}

通过查看这些定义,您可以知道您不能 return 来自 React.FC 的数组。解决方案是将您的 return 值包装在像

这样的反应片段中
return (
  <>
    {todos.map(todo => {
      <div key={todo.id}>
        <p>{todo.title}</p>
        <select />
      </div>;
    })}
  </>
);