TypeScript存取LocalStorage类型断言编译正常运行时报错
问题根因
JSON.stringify序列化规则限制:当传入Date类型实例时,会自动调用Date的toISOString()方法,将其转为ISO格式的字符串,不会保留Date的类型信息。JSON.parse反序列化时,仅能将JSON内容转换为字符串、数字、布尔、普通对象、数组、null这类基础JS类型,不会自动识别日期格式字符串并转回Date实例。- 代码中使用的
<ILocalStorageReturnValue<T>>是TypeScript的类型断言,仅在编译阶段做类型声明骗过类型检查器,不会产生任何运行时的类型转换逻辑,因此编译无报错但运行时storageDate实际是字符串类型,调用Date实例方法自然会抛出异常。 - 额外语法问题:调用代码里误把
storageDate属性当成方法加了()调用,就算类型正确也会报不是函数的错误。
正确实现逻辑
核心修复点:
- 避免重复调用
JSON.parse,减少性能损耗和异常概率 - 反序列化完成后,手动将
storageDate字段的字符串传入new Date()构造,还原为真实的Date实例 - 增加JSON解析异常捕获,处理localStorage中存储损坏内容的边界情况
- 调用时去掉属性名后的多余括号,做好空值判断
修正后的完整类代码:
export interface ILocalStorageReturnValue<T>{ storageDate: Date; storedObj: T } export class LocalStorage<T> { constructor(){ if(!window.localStorage) { throw new Error(`[${constants.FrameWorkName}.LocalStorage]:${strings.ErrBrowserNoLclStrg}`) } } public setItem(key: string, val: T): void { if(!key || !val) { throw new Error(`[${constants.FrameWorkName}.LocalStorage.setItem]:${strings.ErrMissingKeyValProp}`) } const saveObj: ILocalStorageReturnValue<T> = { storedObj: val, storageDate: new Date() } window.localStorage.setItem(key, JSON.stringify(saveObj)) } public getItem(key: string): ILocalStorageReturnValue<T> | null { const rawStr = window.localStorage.getItem(key) if(!rawStr) return null try { const parsedResult = JSON.parse(rawStr) // 手动还原Date类型,保证运行时类型匹配 return { storedObj: parsedResult.storedObj as T, storageDate: new Date(parsedResult.storageDate) } } catch (err) { // 存储内容损坏时清除无效缓存,返回空 window.localStorage.removeItem(key) return null } } }
正确调用示例:
const storageInstance = new LocalStorage<IImage>() const storedData = storageInstance.getItem(constants.localStorageKey) // 先做空值判断,再访问属性,注意storageDate是属性不是方法,不要加() if(storedData) { console.log(storedData.storageDate.toDateString()) }
补充说明:如果你存储的泛型T内部本身也包含Date类型的字段,需要在反序列化时递归遍历对象,将对应日期字段手动还原为Date实例,JSON原生序列化/反序列化能力不支持自动处理这类复杂类型转换。
内容的提问来源于stack exchange,提问作者punjabi
相关产品推荐
相关产品推荐

