NgRx如何扩展EntityState与EntityAdapter添加缓存且兼容原有类型
完全可以实现,核心是通过TypeScript的类型复用能力,仅重写你修改过的方法签名,其余属性完全继承原EntityAdapter类型,不需要从头定义独立类型。
实现步骤
- 定义扩展后的适配器类型
通过Omit剔除原EntityAdapter中你要修改的方法,再重写这些方法的入参和返回值为自定义的CachedEntityState,其余未修改的方法完全复用原类型:
import type { EntityAdapter, EntityState, IdSelector, Comparer, Dictionary } from '@ngrx/entity'; // 已定义的缓存状态接口 export interface CachedEntityState<T> extends EntityState<T> { cache: Dictionary<T>; } // 扩展后的缓存适配器类型:继承原适配器所有未修改的属性,仅重写调整过的方法 export interface CachedEntityAdapter<T> extends Omit<EntityAdapter<T>, 'setAll' /* 后续新增的patch方法都在此处列出来,比如addMany、upsertMany等 */> { setAll: (entities: T[], state: CachedEntityState<T>) => CachedEntityState<T>; // 其他你扩展的方法也在这里补全签名 }
- 为
patchMethods明确指定返回类型,同时补全创建方法的返回值:
// 根方法,明确返回扩展后的CachedEntityAdapter export const createCachedEntityAdapter = <T>(options?: { selectId?: IdSelector<T>; sortComparer?: false | Comparer<T>; }): CachedEntityAdapter<T> => { const cacheAdapter = createEntityAdapter({ selectId: options.selectId, sortComparer: options.sortComparer }) return patchMethods(cacheAdapter); } // 明确返回类型为CachedEntityAdapter<T> const patchMethods = <T>(adapter: EntityAdapter<T>): CachedEntityAdapter<T> => { const newSetAll = patchArrayMethod(adapter.setAll, adapter) return { ...adapter, setAll: newSetAll, } as CachedEntityAdapter<T> } // 原有patch逻辑保持不变 const patchArrayMethod = <T, S extends CachedEntityState<T>>(method: (entities: T[], state: S) => S, adapter: EntityAdapter<T>): (entities: T[], state: S) => S => { return (entities: T[], state: S) => { return method(entities, { ...state, cache: saveCache(entities, state, adapter.selectId) }) } } const saveCache = <T, S extends CachedEntityState<T>>(entities: T[], state: S, selectId: IdSelector<T>): Dictionary<T> => { const newCache = entities.reduce((acc, curr) => { const id = selectId(curr); return { ...acc, [id]: curr } }, {} as Dictionary<T>); return { ...state.cache, ...newCache } }
效果说明
- 所有未修改的原
EntityAdapter方法(比如addOne、removeOne等)会完全继承原类型提示,不需要额外定义 - 你重写的
setAll等方法会自动识别CachedEntityState类型,不会出现类型不兼容问题 - 后续如果需要扩展更多方法,只需要在
CachedEntityAdapter接口里追加对应方法的签名,同时在patchMethods里补充patch逻辑即可
内容的提问来源于stack exchange,提问作者simply good
相关产品推荐
相关产品推荐

