菜单

TypeScript 集成

相关源文件

本页介绍如何将 TypeScript 与 Redux 应用程序集成,以提供类型安全性和改进的开发体验。它解释了为 Redux 存储、动作、reducer 以及与 Redux 状态交互的 React 组件进行类型定义的推荐模式。

有关如何将 TypeScript 添加到项目设置的信息,请参阅项目结构和组织

Redux 中 TypeScript 优势概述

在 Redux 中使用 TypeScript 具有以下几个主要优势:

  1. 对 reducer、状态和动作创建者进行类型安全
  2. 通过智能提示和自动完成提供更好的开发体验
  3. 更容易重构类型化代码
  4. 通过在开发过程中捕获类型错误来防止运行时错误
  5. 自文档化代码,清晰指示预期的数据结构

来源:docs/usage/UsageWithTypescript.md, docs/tutorials/typescript.md

标准 Redux TypeScript 设置

存储配置

使用 TypeScript 设置存储的推荐方法包括:

  1. 使用 Redux Toolkit 的 configureStore 创建存储
  2. 从存储中提取类型定义
  3. 为组件创建预类型化的 Hooks

来源:docs/usage/UsageWithTypescript.md:49-76, docs/tutorials/essentials/part-3-data-flow.md:205-231

核心类型定义

来源:docs/usage/UsageWithTypescript.md:49-74, docs/tutorials/typescript.md:42-61

类型化 Hooks

创建预类型化的 React-Redux Hooks,以简化组件中的类型定义

来源:docs/usage/UsageWithTypescript.md:77-116, docs/tutorials/typescript.md:62-79

这种方法消除了每次使用 useSelector 时都必须指定 RootState 类型,并确保 useDispatch 正确处理 thunk 和其他中间件。

Redux Slices 的类型定义

Slice 状态和动作

在使用 Redux Toolkit 的 createSlice 定义一个 Slice 时,您应该:

  1. 为您的 Slice 状态定义 TypeScript 接口
  2. 正确类型化初始状态
  3. 使用 PayloadAction<T> 来类型化动作负载

来源:docs/usage/UsageWithTypescript.md:122-170, docs/tutorials/essentials/part-3-data-flow.md:275-290

来源:docs/usage/UsageWithTypescript.md:122-182

异步逻辑的类型定义

Thunks 的类型定义

Redux thunks 需要正确的类型定义,以确保整个异步流程的类型安全

来源:docs/usage/UsageWithTypescript.md:226-270, docs/tutorials/essentials/part-5-async-logic.md:226-249

使用 createAsyncThunk

Redux Toolkit 的 createAsyncThunk 简化了异步操作的类型定义

来源:docs/usage/UsageWithTypescript.md:265-302, docs/tutorials/essentials/part-5-async-logic.md:266-297

来源:docs/tutorials/essentials/part-5-async-logic.md:402-517

将 Redux 与 React 和 TypeScript 结合使用

组件用法

在 React 组件中利用类型化 Hooks

来源:docs/usage/UsageWithTypescript.md:326-351, docs/tutorials/typescript.md:151-183

选择器的类型定义

用于从 Redux 存储中选择数据

来源:docs/tutorials/essentials/part-4-using-data.md:475-526

高级 TypeScript 模式

类型安全的规范化数据

在使用 createEntityAdapter 处理规范化状态时

来源:docs/tutorials/essentials/part-6-performance-normalization.md

将 RTK Query 与 TypeScript 结合使用

RTK Query 对 TypeScript 提供了第一类支持

来源:docs/tutorials/essentials/part-7-rtk-query-basics.md:156-183, docs/tutorials/essentials/part-8-rtk-query-advanced.md:66-84

最佳实践和建议

  1. 始终定义您的状态类型:为每个 slice 的状态结构定义明确的接口。

  2. 对动作负载使用 PayloadAction<T>:这确保了动作内容的正确类型定义。

  3. 创建预类型化的 Hooks:一次性定义 useAppSelectoruseAppDispatch Hooks,以简化组件的使用。

  4. 明确类型化选择器:选择器应明确引用 RootState 作为它们的第一个参数。

  5. 不要过度限制类型:在保持类型安全的同时,酌情允许灵活性。

  6. TypeScript 配置:

    • tsconfig.json 中使用严格模式
    • 考虑启用 noImplicitAnystrictNullChecks
  7. 对异步 thunks 使用 .withTypes():创建了解您的存储配置的 createAsyncThunk 的预类型化版本。

  8. 对照 API 模式进行检查:确保您的接口与 API 预期类型匹配。

  9. 避免使用 any:当类型确实不确定时,改用 unknown

  10. 不要过度导出类型:只导出跨文件需要的类型。

来源:docs/usage/UsageWithTypescript.md, docs/tutorials/typescript.md

常见 TypeScript 错误及解决方案

错误可能的原因解决方案
"Property does not exist on type 'RootState'"(类型“RootState”上不存在属性)Slice reducer 未添加到存储中将 slice reducer 添加到 configureStore
使用 useSelector 时出现“No overload matches this call”(没有匹配的重载)选择器函数签名不正确确保选择器接受 RootState
"Cannot find name 'AppDispatch'"(找不到名称“AppDispatch”)缺少导入从存储文件中导入 AppDispatch
"'dispatch' is of type 'unknown'"('dispatch' 的类型为 'unknown')使用了未类型化的 useDispatch使用 useAppDispatch hook
"Object is possibly undefined"(对象可能未定义)需要进行空值检查使用可选链或空值检查
"Type instantiation is excessively deep"(类型实例化过深)循环类型引用简化类型结构或使用类型断言

来源:docs/usage/UsageWithTypescript.md, docs/tutorials/typescript.md

下一步

在 Redux 应用程序中建立 TypeScript 后,您可能想探索:

来源:docs/usage/UsageWithTypescript.md, docs/usage/WritingTests.mdx