如何在TypeScript中确保缓存删除时键与对应值的类型匹配?
问题描述
需要实现缓存删除函数cacheDel,要求当传入的value类型与指定key在对应元素类型中的类型不匹配时,TypeScript能抛出类型错误。当前实现中,value的类型被定义为T[keyof T],这会允许传入任何属于T属性的类型,无法约束到当前选中的key对应的类型。
示例错误调用:
type ItemA = { id: number; name: string; isPrivate: boolean }; // 预期触发错误:`id`应为number类型,却传入字符串 cacheDel<ItemA>(cacheStore, "arrayOfItemA", "id", "not-a-number");
完整初始代码:
type CacheStore = Record<string, unknown[]>; const cacheGet = <T>(store: CacheStore, hash: keyof CacheStore) => { return store[hash] as T[]; }; const cachePut = <T>(store: CacheStore, hash: keyof CacheStore, array: T[]) => { return (store[hash] = array); }; const cacheDel = <T>(store: CacheStore, hash: keyof CacheStore, key: keyof T, value: T[keyof T]) => { const data = cacheGet<T>(store, hash); const updatedData = [...data.filter((item) => item[key] !== value)]; cachePut(store, hash, updatedData); }; type ItemA = { id: number; name: string; isPrivate: boolean }; type ItemB = { token: string; label: string; counter: number }; const cacheStore = { arrayOfItemA: [ { id: 1, name: "item A", isPrivate: true }, { id: 2, name: "item AA", isPrivate: false }, ], arrayOfItemB: [ { token: "aaaaa", label: "hello" }, { token: "bbbbb", label: "bye" }, ], }; cacheDel<ItemA>(cacheStore, "arrayOfItemA", "id", "not-a-number"); // 应触发错误 cacheDel<ItemB>(cacheStore, "arrayOfItemB", "token", 1); // 应触发错误
解决方案
核心问题是原cacheDel的泛型仅定义了T,没有将key和value的类型绑定。我们需要新增泛型参数K来约束key的具体类型,同时让value的类型严格对应T[K],实现类型匹配检查。
修改后的cacheDel函数:
const cacheDel = <T, K extends keyof T>( store: CacheStore, hash: keyof CacheStore, key: K, value: T[K] ) => { const data = cacheGet<T>(store, hash); const updatedData = [...data.filter((item) => item[key] !== value)]; cachePut(store, hash, updatedData); };
改动说明
- 新增泛型参数
K extends keyof T:明确key必须是T的属性名,同时保留key的具体类型信息。 - 将
value的类型从T[keyof T]改为T[K]:让value的类型严格匹配选中key在T中的属性类型,传入不匹配类型时TypeScript会直接抛出错误。
修改后,之前的错误调用会被正确识别:
cacheDel<ItemA>(cacheStore, "arrayOfItemA", "id", "not-a-number"):提示"not-a-number"无法赋值给number类型。cacheDel<ItemB>(cacheStore, "arrayOfItemB", "token", 1):提示1无法赋值给string类型。
内容的提问来源于stack exchange,提问作者Alex Conrad
相关产品推荐
相关产品推荐

