如何实现带类型映射返回值的TypeScript版localStorage封装
实现方案
TypeScript 原生支持这种根据传入键名自动推导返回值类型的场景,核心是通过泛型将入参key的类型和Schema中对应值的类型做绑定,完全不需要手动传入泛型参数。
核心修改点
- 给
get、set方法增加泛型参数<K extends keyof LocalStorageSchema>,将入参key的类型声明为K get方法的返回值类型直接写为LocalStorageSchema[K] | null,TS会根据调用时传入的key字面量自动推导K的具体类型,进而得到对应的值类型,不会再返回所有类型的联合- 原生localStorage只能存储字符串,所以
set方法存值时需要做JSON序列化,get方法取值时做反序列化,才能和你定义的非字符串类型(比如number、对象、布尔值)匹配,同时set方法的value类型也绑定为LocalStorageSchema[K],存值时会自动做类型校验
完整实现代码
type LocalStorageSchema = { token: string; some_string: string; some_number: number; // 可任意扩展支持的类型,比如布尔值、对象、数组都可以 // isLogin: boolean; // userInfo: { id: number; name: string }; }; export const LocalStorage = { get<K extends keyof LocalStorageSchema>(key: K): LocalStorageSchema[K] | null { const rawData = window.localStorage.getItem(key); if (rawData === null) { console.error(`localStorage 中不存在键为 ${key} 的值`); return null; } try { // 反序列化后返回,和set方法的序列化逻辑对应 return JSON.parse(rawData) as LocalStorageSchema[K]; } catch (err) { console.error(`解析localStorage中键 ${key} 的值失败`, err); return null; } }, set<K extends keyof LocalStorageSchema>(key: K, value: LocalStorageSchema[K]) { // 序列化后存储,兼容所有JSON支持的类型 window.localStorage.setItem(key, JSON.stringify(value)); }, remove(key: keyof LocalStorageSchema) { window.localStorage.removeItem(key); }, clear() { window.localStorage.clear(); } };
使用效果
- 调用
LocalStorage.get("some_number")时,TS自动推导返回值类型为number | null - 调用
LocalStorage.get("token")时,自动推导返回值类型为string | null - 调用
LocalStorage.set("some_number", "123")时会直接报类型错误,因为some_number对应的值类型必须是number,从根源避免存错类型
关于函数内部类型收窄的说明
泛型函数内部TS不会自动根据key做跨分支的类型收窄,这是TS的设计特性,不是bug。如果确实需要在函数内部针对不同key做特殊处理,可以通过自定义类型守卫或者显式类型断言实现,外层的类型安全已经由泛型约束保证,只要内部逻辑和Schema定义一致就不会有类型问题。
如果不需要特殊处理个别类型,直接用上面统一JSON序列化/反序列化的方案即可,不需要写分支判断,覆盖绝大多数业务场景。
内容的提问来源于stack exchange,提问作者ronituohino
相关产品推荐
相关产品推荐

