typescript 在不推荐使用全局JSX命名空间之后,JSX.Element的正确返回类型替换是什么?

ryoqjall  于 2023-05-19  发布在  TypeScript
关注(0)|答案(1)|浏览(293)

@types/react中,全局JSX命名空间已被弃用:

declare global {
    /**
     * @deprecated Use `React.JSX` instead of the global `JSX` namespace.
     */
    namespace JSX {
    ...
    }
}

由于我启用了ESLint的deprecation/deprecation规则(来自eslint-plugin-deprecation插件),我现在收到了如下函数组件返回类型的错误:

export default function TestComponent(): JSX.Element { // This JSX is marked as deprecated
    return (
        <span>Test</span>
    );
}

在这种情况下,既然全局JSX命名空间已被弃用,那么JSX.Element的正确返回类型替换是什么?
是否是React.JSX.Element,如弃用消息中所述:

export default function TestComponent(): React.JSX.Element { ... }

ReactElement是这样的:

import { ReactElement } from "react";
export default function TestComponent(): ReactElement { ... }

或者最好使用React.FC声明函数组件,并让TypeScript像这样推断返回类型:

export const TestComponent: React.FC = () => { ... };
olqngx59

olqngx591#

直接使用React.ReactElement(或者更精确地说,React.ReactElement | null):

import { ReactElement } from "react";

export function TestComponent(): ReactElement | null {
  return (
    Math.random() < 0.5
      ? null
      : <>
          A single Element (could be a Fragment like here)
        </>
  );
}

这正是React.FC所执行的(不再推荐):

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

它也是JSXElementConstructor的定义:

type JSXElementConstructor<P> =
  | ((props: P) => ReactElement<any, any> | null) // Case of a Function Component
  | (new (props: P) => Component<any, any>); // Case of a Class-based Component

也就是说,除非你有一些规则强迫你输入你的函数组件返回类型,否则你可以为了简单而省略它:

export function TestComponent() {
  // ...
}

显然,该函数现在可以返回任何内容,并且TypeScript不会抱怨......除非您尝试将其用作JSX模板中的函数组件,如fb/cra#8177中所指出的:
我真正看到React.FC [...]的唯一好处是它指定了返回类型,这会捕获错误[...]
在实践中,我认为这是好的,因为一旦你尝试使用它,它就会被捕获:

const Example = () => <Component />; // Error here, due to Component returning the wrong thing

相关问题