TypeScript y StorageManager

TypeScript y StorageManager

Este artículo explica TypeScript y StorageManager.

Proporcionamos ejemplos prácticos para explicar TypeScript y StorageManager.

YouTube Video

TypeScript y StorageManager

¿Qué es StorageManager?

StorageManager es una API que permite a las aplicaciones web estimar cuánta memoria están utilizando y cuánta capacidad está disponible. También proporciona una solicitud de persistencia (persist()) para evitar la eliminación automática de datos por parte del usuario o del navegador. Esto te permite controlar si hay suficiente espacio libre o si los datos se eliminarán automáticamente, como al almacenar grandes cantidades de datos en IndexedDB para aplicaciones sin conexión.

Detección de características

Primero, verifica si el navegador soporta navigator.storage.

 1// TypeScript: feature detection for StorageManager
 2function supportsStorageManager(): boolean {
 3  return typeof navigator !== "undefined" &&
 4         typeof navigator.storage !== "undefined" &&
 5         typeof navigator.storage.estimate === "function";
 6}
 7
 8// Example usage
 9if (supportsStorageManager()) {
10  console.log("StorageManager is supported.");
11} else {
12  console.warn("StorageManager not supported. Falling back to localStorage or IndexedDB.");
13}
  • Esta función verifica la disponibilidad de la API StorageManager en etapas.
  • Como navigator.storage no existe en algunos navegadores como Safari, es importante comprobar su existencia de manera segura usando typeof.

Estimar el uso de almacenamiento (estimate())

Después de comprobar la funcionalidad con supportsStorageManager(), obtén el uso (usage) y la cuota (quota) de navigator.storage.estimate().

 1// TypeScript: safely get storage estimate
 2async function getStorageEstimate(): Promise<{ usage: number; quota: number } | null> {
 3  if (!supportsStorageManager()) {
 4    console.warn("StorageManager not supported.");
 5    return null;
 6  }
 7
 8  const estimate = await navigator.storage.estimate();
 9  return { usage: estimate.usage ?? 0, quota: estimate.quota ?? 0 };
10}
11
12// Example usage
13getStorageEstimate().then(result => {
14  if (result) {
15    console.log(`Usage: ${result.usage} bytes / Quota: ${result.quota} bytes`);
16  }
17});
  • Esta función siempre funciona de forma segura y devuelve null si el navegador no la soporta.
  • usage y quota son estimaciones y pueden variar entre navegadores.

Solicitar persistencia de datos (persist())

Utiliza persist() para solicitar persistencia, de modo que los datos importantes (por ejemplo, caché offline) no estén sujetos a eliminación automática por parte del navegador. Sin embargo, no tiene éxito en todos los entornos.

 1// TypeScript: safely request persistent storage
 2async function requestPersistence(): Promise<boolean> {
 3  if (!supportsStorageManager()) {
 4    console.warn("StorageManager not supported.");
 5    return false;
 6  }
 7
 8  if (typeof navigator.storage.persist !== "function") {
 9    console.warn("persist() not available in this browser.");
10    return false;
11  }
12
13  try {
14    const granted = await navigator.storage.persist();
15    return Boolean(granted);
16  } catch (err) {
17    console.error("persist() error:", err);
18    return false;
19  }
20}
21
22// Example usage
23requestPersistence().then(granted => {
24  console.log("Persistence granted?", granted);
25});
  • Si persist() tiene éxito, los datos no serán eliminados automáticamente por el navegador, salvo intervención manual del usuario. Sin embargo, las solicitudes pueden ser rechazadas dependiendo de las acciones del usuario o la configuración del navegador.

Verificar el espacio disponible antes de guardar datos

Verifica el espacio disponible antes de guardar grandes cantidades de datos para evitar errores de escritura (QuotaExceededError).

 1// TypeScript: ensure enough space before writing
 2async function ensureSpaceAndWrite(neededBytes: number, writeFn: () => Promise<void>): Promise<boolean> {
 3  const estimate = await getStorageEstimate();
 4  if (!estimate) {
 5    console.warn("Cannot check storage space. Proceeding without validation.");
 6    await writeFn();
 7    return true;
 8  }
 9
10  const free = estimate.quota - estimate.usage;
11  if (free < neededBytes) {
12    console.warn(`Not enough space. Free: ${free} bytes, needed: ${neededBytes} bytes.`);
13    return false;
14  }
15
16  await writeFn();
17  return true;
18}
19
20// Example usage
21ensureSpaceAndWrite(10 * 1024 * 1024, async () => {
22  console.log("Saving large data...");
23});
  • Al comprobar el almacenamiento disponible antes de guardar, puedes reducir el riesgo de interrupciones en la escritura debido a la capacidad insuficiente.

Manejo seguro de tipos en localStorage con TypeScript

localStorage es conveniente para almacenar datos de configuración ligeros y otra información similar.

La siguiente clase utiliza genéricos para crear un wrapper seguro en cuanto a tipos.

 1// TypeScript: typed localStorage wrapper
 2type Serializer<T> = {
 3  serialize: (v: T) => string;
 4  deserialize: (s: string) => T;
 5};
 6
 7class TypedLocalStorage<K extends string, V> {
 8  constructor(private storage: Storage, private serializer: Serializer<V>) {}
 9
10  set(key: K, value: V): void {
11    this.storage.setItem(key, this.serializer.serialize(value));
12  }
13
14  get(key: K): V | null {
15    const raw = this.storage.getItem(key);
16    if (raw === null) return null;
17    try {
18      return this.serializer.deserialize(raw);
19    } catch {
20      return null;
21    }
22  }
23
24  remove(key: K): void {
25    this.storage.removeItem(key);
26  }
27
28  clear(): void {
29    this.storage.clear();
30  }
31}
32
33// Example usage
34const jsonSerializer: Serializer<any> = {
35  serialize: v => JSON.stringify(v),
36  deserialize: s => JSON.parse(s),
37};
38
39const appStorage = new TypedLocalStorage<'theme' | 'token', any>(localStorage, jsonSerializer);
40appStorage.set('theme', { dark: true });
41console.log(appStorage.get('theme'));
  • Esta clase ayuda a reducir el riesgo de almacenar o recuperar datos con el tipo incorrecto.

Consideraciones prácticas y buenas prácticas

  • Comprueba siempre si el navegador soporta StorageManager Dado que StorageManager es una API relativamente nueva, confirma siempre su existencia antes de usarla.

  • Presta atención a los límites de almacenamiento y la compatibilidad El valor devuelto por estimate() varía según el navegador y es solo una estimación.

  • Diseña teniendo en cuenta las API asíncronas estimate() y persist() son API asíncronas basadas en promesas. Diseña tu código para que no bloquee la interfaz de usuario.

  • Consideraciones de seguridad No almacenes información sensible como tokens de acceso en localStorage. Considera usar cookies HttpOnly o cifrado si es posible.

  • Diseño de respaldo (fallback) Si supportsStorageManager() devuelve falso, proporciona una lógica para cambiar a usar solo localStorage o IndexedDB.

Resumen

Con la detección de características utilizando supportsStorageManager(), puedes soportar de forma segura todos los entornos, comprobar el uso y la cuota con navigator.storage.estimate() y solicitar persistencia con persist(). En TypeScript, utiliza funciones wrapper y definiciones de tipos para escribir código legible y seguro. El flujo básico es: comprobar existencia, estimar, solicitar persistencia y verificar la capacidad antes de escribir en el almacenamiento.

Puedes seguir el artículo anterior utilizando Visual Studio Code en nuestro canal de YouTube. Por favor, también revisa nuestro canal de YouTube.

YouTube Video