import * as _ from './utils' export class Storage { clear(): void { _.internalsOf(this, 'Storage', 'clear').storage.clear() } getItem(key: string): string | null { return getStringOrNull( _.internalsOf(this, 'Storage', 'getItem').storage.get(String(key)) ) } key(index: number): string | null { return getStringOrNull([ ..._.internalsOf(this, 'Storage', 'key').storage.keys() ][Number(index) || 0]) } removeItem(key: string): void { _.internalsOf(this, 'Storage', 'getItem').storage.delete(String(key)) } setItem(key: string, value: any): void { _.internalsOf(this, 'Storage', 'getItem').storage.set(String(key), String(value)) } get length() { return _.internalsOf(this, 'Storage', 'size').storage.size } } const getStringOrNull = (value: string | void) => typeof value === 'string' ? value : null export const initStorage = (target: Target, exclude: Set) => { if (exclude.has('Storage') || exclude.has('localStorage')) return target.localStorage = Object.create(Storage.prototype) const storageInternals = new Map() _.INTERNALS.set(target.localStorage, { storage: storageInternals } as StorageInternals) } interface StorageInternals { storage: Map } interface Target { localStorage: Storage }