为 TypeScript 定义非箭头 React 函数组件是什么?

15

你可以使用下面的代码在TypeScript中定义React函数组件的类型:

export const Component: React.FC = () => {
  return // Stuff
};

如何对非箭头函数执行相同操作?

function Component() {
  return // Stuff
}

有什么实践上的区别吗?这份流行的速查表没有涵盖它,所以我想知道是否有不使用该语法的原因?

https://github.com/typescript-cheatsheets/react-typescript-cheatsheet


有用的解释:https://blog.echobind.com/react-with-typescript-components-as-function-declarations-vs-function-expressions-e433ac8d6938。似乎由于Typescript的限制,您会失去类型信息:https://github.com/Microsoft/TypeScript/issues/22063。 - vaughan
3个回答

6
如何对非箭头函数进行相同的操作?
import * as React from 'react';

function NonFatArrow(): React.ReactElement {
    return (
      <>
        Non-fat-arrow function
      </>
    );
}

const FatArrow: React.FunctionComponent = _props => {
  return (
    <section>
      <NonFatArrow/>
    </section>
  );
};


有没有实践上的区别?
除了 React 和 TypeScript,ES6 中的箭头函数会捕获一些东西,包括 `this`,并将其随自身一起传递。因此,如果有成千上万个这样的函数,则将捕获的开销会很大。
回到 React 和 TypeScript,`this` 在 React.FunctionComponent(s) 中没有用到,但是如果您选择的 Typescript 转译器转译为 ES6,则会有带有捕获的箭头函数。
所以这都取决于所选的转译器及其设置。使用 Typescript 编译器,如果您在 tsconfig.json 中具有 "target": "es5",则 FatArrow 组件将被转译为 ES5 函数。将设置更改为 "target": "es6" 可确保 FatArrow 转译为箭头函数。使用 Babel 作为转译器时可能会有所不同。

这并没有真正解决你的问题,因为在你的例子中 NonFatArrow 不是一个 React.FC,因此你将无法获得任何好处。尝试在其中使用 children 属性,TypeScript 将会报错。 - Charlie Martin

4

当你使用const声明组件时,某些情况下会有更好的类型支持。要了解这些情况,您可以查看React.FC类型:

type FC<P = {}> = FunctionComponent<P>;
interface FunctionComponent<P = {}> {
    (props: PropsWithChildren<P>, context?: any): ReactElement | null;
    propTypes?: WeakValidationMap<P>;
    contextTypes?: ValidationMap<any>;
    defaultProps?: Partial<P>;
    displayName?: string;

}

由于React组件(即使是函数组件)要比普通函数略微复杂-为组件本身指定精确类型可以带来更好的类型推断:


function FooAsFunc({ children }) { // children has 'any' type
  return 1234
}

const FooAsConst: React.FC = ({ children }) => {
  return 1234 // type error: typescript knows that 1234 is not valid react component return type
}

FooAsFunc.displayName = new Date()
FooAsConst.displayName = new Date() // type error: 'displayName' suppose to be of a type string

最终,你也可以通过function声明实现相同的类型安全性,但这需要更多的代码。

2

如果您想使用完整的函数类型来定义非箭头函数,可以像这样使用 (typescript 文档):

let myAdd: (x: number, y: number) => number =
    function(x: number, y: number): number { return x + y; };

在您的情况下:
const MyComponent: React.FC = function() {
  return <div></div>;
};

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接