Imagina que cada vez que abres un archivo o una conexión de base de datos el compilador te recordara cerrar ese recurso automáticamente. Esa es la promesa del nuevo keyword using en TypeScript, y hoy lo vamos a desmenuzar.<\/p>

Foto por Mohammad Rahmani en Unsplash

Tabla de contenidos

¿Qué es using?

Introducido en TypeScript 5.2, using permite declarar variables cuyo ciclo de vida está ligado a un bloque de código. Cuando el bloque termina, el runtime invoca automáticamente el método dispose del objeto, liberando recursos como archivos, sockets o manejadores de memoria.

Foto por kenny cheng en Unsplash

Gestión explícita de recursos: patrones y buenas prácticas

Para aprovechar al máximo using, sigue estos principios:

  • Implementa la interfaz Disposable con un método dispose() que realice la limpieza.

  • Limita el alcance del recurso al bloque donde realmente se necesita.

  • No mezcles lógica de negocio y liberación; mantén la responsabilidad de dispose aislada.

A continuación un ejemplo de una clase FileHandle que sigue este patrón:

class FileHandle implements Disposable {
  private readonly fd: number;
  constructor(path: string) {
    this.fd = Deno.openSync(path).rid;
  }
  read(): Uint8Array {
    const buf = new Uint8Array(1024);
    Deno.readSync(this.fd, buf);
    return buf;
  }
  dispose(): void {
    Deno.close(this.fd);
    console.log('Archivo cerrado');
  }
}

// Uso con using
using file = new FileHandle('datos.txt');
const contenido = file.read();
console.log(new TextDecoder().decode(contenido));
// Al salir del bloque, file.dispose() se llama automáticamente

Comparativa con try...finally y otras lenguas

Antes de using, la forma tradicional en JavaScript era envolver el recurso en un try y garantizar su cierre en el finally. El código era más verboso y propenso a errores, especialmente cuando se olvidaba el finally o se lanzaban excepciones antes de llegar a él.

Lenguas como C# o Rust ya contaban con construcciones similares (using en C# y el trait Drop en Rust). La incorporación de este mecanismo en TypeScript cierra la brecha y nos brinda una API coherente en todo el ecosistema JavaScript.

Implementación práctica: ejemplo real

Supongamos que tienes una API que necesita abrir una conexión a una base de datos en cada petición. Con using puedes asegurarte de que la conexión se libere sin importar si la petición falla.

class DbConnection implements Disposable {
  constructor(private readonly config: string) {
    // Simulación de apertura de conexión
    console.log('Conexión abierta');
  }
  query(sql: string): any {
    // Simular consulta
    return { rows: [] };
  }
  dispose(): void {
    console.log('Conexión cerrada');
  }
}

function handler(request: Request): Response {
  using conn = new DbConnection('postgres://user:pass@host/db');
  const result = conn.query('SELECT * FROM usuarios');
  return new Response(JSON.stringify(result), { status: 200 });
  // Si ocurre cualquier error, conn.dispose() se ejecuta automáticamente
}

Este patrón simplifica la gestión de recursos y reduce significativamente la superficie de errores relacionados con fugas de memoria o conexiones abiertas.

Conclusión

El keyword using llega en el momento justo para que los proyectos TypeScript adopten una gestión de recursos segura y concisa. Integra la interfaz Disposable, mantén los alcances limitados y olvídate de los tradicionales bloques try...finally. La próxima vez que abras un archivo, una socket o una conexión a DB, hazlo con using y deja que el compilador se encargue del resto.

Referencias