using (resurse) în TypeScript

Cod asincron și iterare TypeScript 5.2

Declară o resursă care se eliberează automat la ieșirea din bloc, chiar dacă apare o eroare.

Sintaxă
{
    using resursa = obiectCuSymbolDispose;
    await using conexiune = obiectCuSymbolAsyncDispose;
}   // aici se apelează automat [Symbol.dispose]() / [Symbol.asyncDispose]()

Ce face using (resurse)

using declară o variabilă ca const, dar cu o promisiune în plus: când execuția iese din blocul curent (normal, cu return sau printr-o eroare), se apelează automat metoda [Symbol.dispose]() a obiectului. Este echivalentul lui try/finally pentru fișiere deschise, conexiuni, blocări sau cronometre, fără să mai scrii finally de mână.

Obiectul trebuie să implementeze interfața Disposable (metoda [Symbol.dispose]). await using lucrează cu AsyncDisposable ([Symbol.asyncDispose], care returnează un Promise) și așteaptă eliberarea. Dacă declari mai multe resurse, sunt eliberate în ordine inversă. DisposableStack adună mai multe resurse sau funcții de curățare într-un singur obiect.

Este o funcție nouă din JavaScript (propunerea „Explicit Resource Management”), suportată de Node.js 24+ și browserele recente; TypeScript o poate transforma pentru medii mai vechi. Tipurile sunt în biblioteca esnext.disposable (incluse și de @types/node).

Exemple

Exemplul 1: Eliberare automată, în ordine inversă

class Resursa implements Disposable {
    constructor(readonly nume: string) {
        console.log("deschid", nume);
    }
    [Symbol.dispose](): void {
        console.log("închid", this.nume);
    }
}

function lucreaza(): string {
    using fisier = new Resursa("note.csv");
    using conexiune = new Resursa("baza de date");
    console.log(`lucrez cu ${fisier.nume} și ${conexiune.nume}`);
    return "gata";
}

console.log(lucreaza());

Rezultat

deschid note.csv
deschid baza de date
lucrez cu note.csv și baza de date
închid baza de date
închid note.csv
gata

Exemplul 2: Eliberare și când apare o eroare

Resursa este închisă înainte ca eroarea să ajungă la catch.

function blocare(nume: string): Disposable {
    console.log(`blochez ${nume}`);
    return { [Symbol.dispose]: () => console.log(`deblochez ${nume}`) };
}

try {
    using _b = blocare("catalog");
    throw new Error("nota nu este validă");
} catch (e) {
    console.log("eroare:", (e as Error).message);
}

Rezultat

blochez catalog
deblochez catalog
eroare: nota nu este validă

Exemplul 3: await using cu un fișier temporar

import { open, rm } from "node:fs/promises";

async function fisierTemporar(nume: string) {
    const f = await open(nume, "w");
    return {
        f,
        async [Symbol.asyncDispose]() {
            await f.close();
            await rm(nume);
            console.log(`${nume} a fost șters`);
        },
    };
}

{
    await using tmp = await fisierTemporar("raport.tmp");
    await tmp.f.writeFile("Ana,10\nMihai,9\n");
    console.log("scris:", (await tmp.f.stat()).size, "octeți");
}
console.log("după bloc");

Rezultat

scris: 15 octeți
raport.tmp a fost șters
după bloc

Greșeli frecvente

  • Folosești using pe un obiect fără [Symbol.dispose]. tsc dă The initializer of a ‘using’ declaration must be either an object with a ‘[Symbol.dispose]()’ method, or be ‘null’ or ‘undefined’.
  • Folosești using pentru o resursă asincronă. Eliberarea nu este așteptată; scrie await using.

Comenzi înrudite

  • bigint și symbol: bigint ține numere întregi oricât de mari; symbol este o valoare unică, folosită de obicei drept cheie de proprietate.
  • async/await cu tipuri: O funcție async returnează mereu Promise<T>; await scoate valoarea de tip T din Promise.
  • implements: O clasă promite că respectă una sau mai multe interfețe; tsc verifică dacă are toți membrii ceruți.
  • interface: Descrie forma unui obiect: ce proprietăți are, de ce tip sunt și ce metode are.