reactjs - 如何在 Typescript 中为 React useReducer 挂钩操作创建类型定义?
问题描述
假设我们这样userReducer
定义:
function userReducer(state: string, action: UserAction): string {
switch (action.type) {
case "LOGIN":
return action.username;
case "LOGOUT":
return "";
default:
throw new Error("Unknown 'user' action");
}
}
定义类型的最佳方法是什么,UserAction
因此可以dispatch
使用username
有效负载和不使用以下方法进行调用:
dispatch({ type: "LOGIN", username: "Joe"}});
/* ... */
dispatch({ type: "LOGOUT" });
如果类型是这样定义的:
type UserActionWithPayload = {
type: string;
username: string;
};
type UserActionWithoutPayload = {
type: string;
};
export type UserAction = UserActionWithPayload | UserActionWithoutPayload;
在“LOGIN”情况下,编译器在减速器中抛出错误:TS2339: Property 'username' does not exist on type 'UserAction'. Property 'username' does not exist on type 'UserActionWithoutPayload'.
如果使用可选成员定义类型:
export type UserAction = {
type: string;
username?: string;
}
然后编译器显示此错误:TS2322: Type 'string | undefined' is not assignable to type 'string'. Type 'undefined' is not assignable to type 'string'.
这里缺少什么?也许整个方法是错误的?
项目使用 TypeScript 3.8.3 和 React.js 16.13.0。
解决方案
enum
经过数小时的挖掘和试验,通过 Typescript和联合类型的操作找到了一个非常优雅的解决方案:
enum UserActionType {
LOGIN = "LOGIN",
LOGOUT = "LOGOUT"
}
type UserState = string;
type UserAction =
| { type: UserActionType.LOGIN; username: string }
| { type: UserActionType.LOGOUT }
function userReducer(state: UserState, action: UserAction): string {
switch (action.type) {
case UserActionType.LOGIN:
return action.username;
case UserActionType.LOGOUT:
return "";
default:
throw new Error();
}
}
function App() {
const [user, userDispatch] = useReducer(userReducer, "");
function handleLogin() {
userDispatch({ type: UserActionType.LOGIN, username: "Joe" });
}
function handleLogout() {
userDispatch({ type: UserActionType.LOGOUT });
}
/* ... */
}
使用上述方法没有错误或警告,此外还有一个非常严格的操作使用合同。
推荐阅读
- asp.net - 如何从选择中自动检查复选框
- object - 使用 typeof === 带有 Flow 错误的自定义类型进行类型检查
- javascript - 如何仅在 k6 负载测试中为每个 VU 使用/分配 CSV 文件中的唯一数据行
- sql - 如果只有第一条记录和最后一条记录,如何在查询中显示创建的记录数
- c# - Unity 播放动画选定的次数
- ssl - 使用 JGIT 克隆 repo 后无法从 CMD 中提取 ..获取 SSL 证书问题:证书链中的自签名证书
- metal - 在金属中绘制 rgb5a1 纹理格式
- .net - 什么可能导致 XUnit 测试批量失败但单独成功?
- r - 如何将两个字符串转换为相同的编码?使用 R
- php - 使用 Webklex\IMAP 在 O365 服务器上获取文件夹的问题