reactjs - 如何在 useReducer 中使用具有必填字段的泛型类型?
问题描述
我正在尝试使用 useReducer 创建一个自定义的 React 钩子。它应该保存对象数组的状态,并且所有对象都必须有一个“id”字段。id 以外的对象结构应该是通用的。
这就是我所拥有的;
export enum ArrayActions { INIT, ADD, UPDATE, DELETE }
type ArrayAction<T> =
| { type: ArrayActions.INIT, payload: T[] }
| { type: ArrayActions.ADD, payload: T }
| { type: ArrayActions.UPDATE, payload: T }
| { type: ArrayActions.DELETE, id: string }
type ObjWithId = { id:any, [key: string]: any }
function arrayReducer<T extends ObjWithId>(state: T[], action: ArrayAction<T>): T[] {
switch(action.type){
case ArrayActions.INIT:
return [...action.payload]
case ArrayActions.ADD: // TODO: check if id already exists
return [...state, action.payload]
case ArrayActions.UPDATE:
return [...(state.filter(item => item.id !== action.payload.id)), action.payload]
case ArrayActions.DELETE:
return state.filter(item => item.id !== action.id)
}
}
export function useArrayReducer<T extends ObjWithId> (initialState: T[] = []): [T[], React.Dispatch<ArrayAction<T>>] {
const [state, dispatch] = useReducer(arrayReducer, initialState)
return [state, dispatch] // error!
}
state
在最后一行给出以下错误;
Type 'ObjWithId[]' is not assignable to type 'T[]'.
Type 'ObjWithId' is not assignable to type 'T'.
我认为它可能与定义有关ObjWithId
,但无法完全弄清楚。你能帮我达到想要的结果吗?
解决方案
万一有人需要;
export interface ListItem {
id: string | number | undefined;
[key: string]: any;
}
export type Action<L extends ListItem> =
| { type: "init", items: L[]}
| { type: "add", item: L }
| { type: "update", item: L }
| { type: "delete", id: NonNullable<L["id"]>}
推荐阅读
- android - Gradle 构建失败:找不到方法 org.gradle.tooling.model.gradle.GradleBuild.getIncludedBuilds
- hive - Hive INSERT INTO vs UNION ALL 性能
- python - Slack API - rtm_connect 错误
- postman - 为什么 Insomnia 开始认不出西里尔字母?
- ionic-framework - Ionic 3 组合标签页和侧边菜单不起作用
- python - 在 Python 中比较两个 Microsoft Excel 文件
- laravel - Laravel 5.6 模型关系和数组
- mysql - 从 MySQL 结果中跳过第一条记录
- ibm-mq - 我们找不到交易
- android - 将 Roomdb 添加到当前项目后。它显示数据绑定错误