React + TypeScript 函数组件类型化完全指南:基于 react-typescript-cheatsheet 的写法、React.FC 争议与 React 19 新实践 React TypeScript 函数组件类型化完全指南基于 react-typescript-cheatsheet 的写法、React.FC 争议与 React 19 新实践【免费下载链接】reactCheatsheets for experienced React developers getting started with TypeScript项目地址: https://gitcode.com/gh_mirrors/reactt/react-typescript-cheatsheet本篇技术指南基于 react-typescript-cheatsheet 仓库中的 函数组件 文档展开系统讲解如何用 TypeScript 为 React 函数组件声明 props 类型、选择是否标注返回类型、何时需要React.FC并结合仓库中 defaultProps、Ref、ReactNode 等参考文档补充 React 19 时代函数组件的现代类型化实践。读完本文你可以直接复制其中的代码模式为函数组件建立完整、可复用的类型契约。函数组件的本质一个接收 props 并返回 JSX 的普通函数Cheatsheet 的核心观点很直接函数组件在 TypeScript 中就是普通的函数——接收一个props参数返回一个 JSX 元素。函数组件 文档给出的完整写法如下// Declaring type of props - see Typing Component Props for more examples type AppProps { message: string; }; /* use interface if exporting so that consumers can extend */ // Easiest way to declare a Function Component; return type is inferred. const App ({ message }: AppProps) div{message}/div; // You can choose to annotate the return type so an error is raised if you accidentally return some other type const App ({ message }: AppProps): React.JSX.Element div{message}/div; // You can also inline the type declaration; eliminates naming the prop types, but looks repetitive const App ({ message }: { message: string }) div{message}/div; // Alternatively, you can use React.FunctionComponent (or React.FC), if you prefer. // With latest React types and TypeScript 5.1. its mostly a stylistic choice, otherwise discouraged. const App: React.FunctionComponent{ message: string } ({ message }) ( div{message}/div ); // or const App: React.FCAppProps ({ message }) div{message}/div;这四种写法构成函数组件类型化的基本组合空间props 类型如何声明命名类型、内联类型与返回类型如何确定隐式推断、显式标注、由React.FC决定。其中两个关键设计点值得展开props 类型用type还是interface。文档注释中给出了实用建议如果 props 类型需要导出供消费者扩展优先使用interface因为它支持声明合并declaration merging否则type更简洁。完整的取舍对照可参考仓库中的 Types or Interfaces 表格那里对两者在联合类型、交叉类型、递归、错误信息展开等维度的差异做了系统比较。返回类型默认让 TypeScript 推断。第一种写法不标注返回类型是文档推荐的最简方式显式标注React.JSX.Element的价值在于形成一道护栏——一旦组件体意外返回了其他类型例如返回了null之外的结构或undefined编译器会立刻报错。Tip: 函数组件 文档还建议借助 VS Code 的 TypeScript 工具包类扩展来自动化类型解构声明这一样板操作输入 props 类型名后自动展开为({ propA, propB }: Props)形式的参数解构并配置键盘快捷键以提升编写效率。为什么React.FC不是必需的在大量 React TypeScript 代码库中你会见到这样的写法const App: React.FunctionComponent{ message: string } ({ message }) ( div{message}/div );但 函数组件 文档记录的当前社区共识是React.FunctionComponent或其简写React.FC并非必需。具体边界如下在最新 React 类型 TypeScript 5.1 的组合下是否使用React.FC主要是一个风格选择如果你仍在使用 React 17 或低于 5.1 的 TypeScript社区甚至明确不鼓励使用React.FC。文档还指出若你认同这一观点并希望从代码库中批量移除React.FC可以借助开源的 jscodeshift codemod 工具完成自动化迁移。React.FunctionComponent与普通函数写法的实质差异有三点文档逐一列出了返回类型的显式性React.FunctionComponent明确声明了返回类型而普通函数写法是隐式的除非额外标注静态属性的类型检查与自动补全它提供了displayName、propTypes、defaultProps等静态属性的类型支持。但文档同时警告defaultProps配合React.FunctionComponent存在已知问题上游 issue 中有详细记录仓库专门维护了独立的 Typing default props 章节来处理这个问题未来的 readonly 语义从类型设计的演进方向看React.FunctionComponent未来可能会自动把 props 标记为readonly——不过只要你在参数列表中对 props 做了解构这一点就无关紧要了。结论是绝大多数场景下两种语法几乎没有差别如果你偏好更显式的类型表达选择React.FunctionComponent也完全可以。返回类型React.JSX.Element、ReactElement与ReactNode的边界显式标注返回类型时应该写什么是函数组件类型化的高频疑问。仓库的 ReactNode 参考文档 给出了明确的三分法ReactNode最宽泛React 可渲染的一切值包括ReactElement、string、number、bigint、boolean、null、undefined、可迭代的节点集合、ReactPortal以及用于异步 Server Components 的PromiseReactNodeReactElement只描述 JSX 或createElement产生的对象——它有type、props、key字段string不是ReactElementReact.JSX.Element本质上就是ReactElementany, any即 JSX 转换对 JSX 表达式推断出的类型。基于这个区分ReactNode 文档 特别强调了一条反模式不要把ReactNode用作函数组件的返回类型。组件的返回类型应该是React 允许组件返回的东西而不是React 允许组件接收的东西——ReactNode包含了bigint、PromiseReactNode等不该从 JSX 组件返回的值。正确做法是// 不推荐范围过宽历史上在 JSX 中使用时引发过问题 const MyComponent (): ReactNode hello; // 推荐让 TS 推断 const MyComponent () hello; // 推荐显式标注 const MyComponent (): React.JSX.Element spanhello/span;这与 函数组件 文档中React.JSX.Element的标注建议完全一致两者互为印证React.JSX.Element是函数组件显式返回类型的标准答案。React 19函数组件默认值与 ref 的现代写法函数组件 文档写于React.FC争议的语境中而仓库中同层的 Typing default props 与 Ref 参考文档 记录了 React 19 带来的两项与函数组件直接相关的重大变化使用最新 React 类型时应一并掌握。defaultProps 不再适用于函数组件自 React 19 起defaultProps在函数组件上不再受支持。正确做法是直接在参数列表中使用解构默认值TypeScript 会自动把对应 prop 推断为可选type GreetProps { age?: number }; const Greet ({ age 21 }: GreetProps) { // ... };如果希望把默认值集中声明以便跨组件共享可以提取为常量并用satisfies约束type GreetProps { age?: number }; const defaultProps { age: 21 } satisfies GreetProps; const Greet ({ age defaultProps.age }: GreetProps) { // ... };文档明确警告在 React 19 中给函数组件设置Greet.defaultProps { age: 21 }不生效——该值在运行时被忽略且FunctionComponent类型也不再接管它的类型。这与上文React.FC提供defaultProps类型检查的差异描述形成演进闭环旧类型中React.FC的一项能力在新 React 中已随运行时能力一起被移除。ref 成为普通 propRef 参考文档 指出在 React 19 中ref是函数组件上的一个普通 prop不再需要forwardRef包装。函数组件接收 ref 的标准写法是直接把它写进 props 类型import { Ref } from react; type FancyInputProps { ref?: RefHTMLInputElement; placeholder?: string; }; function FancyInput({ ref, placeholder }: FancyInputProps) { return input ref{ref} placeholder{placeholder} classNamefancy /; }其中RefT是RefCallbackT | RefObjectT | null | null的联合类型作为接受方的 prop 类型使用——因为调用方可能传入RefObject或回调任一形式。若 ref 不属于根元素同样可以把它透传给内部元素useImperativeHandle在 React 19 中也直接以refprop 为参数调用。如果你仍需要维护 React 19 之前的代码仓库中的 forwardRef/createRef 章节 保留了forwardRefHandle, Props的旧式写法与泛型 forwardRef 的三种方案。用ComponentProps反推函数组件的 props 类型当你需要复用某个函数组件已有的 props 类型时ComponentProps 参考文档 提供了工具函数。它对元素类型和组件类型都有效因此对函数组件一样适用interface Props { text: string; } function Component(props: Props) { // ... } type MyType ComponentPropstypeof Component; // ^? type MyType Props还可以索引推断结果提取某个具体 prop 的类型例如组件库没有导出 icon 名称类型时import { Icon } from component-library; type IconName ComponentPropstypeof Icon[name];types/react中还有两个相关变体文档 用表格总结了适用场景ComponentPropsWithRefT额外并入refReact 19 中对函数组件结果与ComponentPropsT相同因为 ref 本就是普通 propComponentPropsWithoutRefT则剥离ref适合把 props 透传spread给子元素、又不希望ref泄漏的场景。与类组件写法的对照函数组件 是仓库 Getting Started 章节中列在 类组件 之前的第一张卡片两者构成对照关系类组件通过泛型继承声明契约class App extends React.ComponentMyProps, MyStateprops 由React.ComponentP, S自动标记为不可变无需手写readonly函数组件没有 state 类型参数类型契约集中在 props 与返回类型两处类组件仍支持static defaultProps且推荐把有默认值的键在 props 类型中声明为必填由 JSX 层自动应用的React.JSX.LibraryManagedAttributes在调用处将其变为可选——详见 Typing default props 的类组件部分。实践要点小结结合 函数组件 主文档与仓库配套参考文档函数组件的类型化可以收敛为一套清晰的决策路径props 类型内部使用用type需要导出供消费者扩展声明合并时用interface返回类型优先让 TypeScript 推断需要护栏时标注React.JSX.Element避免使用过宽的ReactNodeReact.FC在最新 React 类型 TypeScript 5.1 下可视为风格选择React 17 / 旧版 TS 环境甚至不鼓励注意其defaultProps类型支持在新 React 中已失效默认值React 19 下用参数解构默认值配合satisfies提取常量不要再给函数组件挂defaultPropsrefReact 19 下直接把ref?: RefT写进 props无需forwardRef复用他人 props用ComponentPropstypeof Component或带/不带 ref 的变体反推并索引。上述写法均基于仓库对最新 React 与 TypeScript 版本的假设见 Introduction如果你的项目锁定在 React ≤ 18 或旧版 TypeScriptforwardRef与ComponentPropsWithRef等旧式 API 仍是必要手段。仓库文档均位于docs/basic/getting-started/与docs/reference/目录下可对照查阅。【免费下载链接】reactCheatsheets for experienced React developers getting started with TypeScript项目地址: https://gitcode.com/gh_mirrors/reactt/react-typescript-cheatsheet创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考