You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NgRx如何扩展EntityState与EntityAdapter添加缓存且兼容原有类型

完全可以实现,核心是通过TypeScript的类型复用能力,仅重写你修改过的方法签名,其余属性完全继承原EntityAdapter类型,不需要从头定义独立类型。

实现步骤

  1. 定义扩展后的适配器类型
    通过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>;
    // 其他你扩展的方法也在这里补全签名
}
  1. 为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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 02:36:08