Das neue 'using' - Feature von TypeScript 5.2

TypeScript hat in der Version 5.2 ein neues Schlüsselwort eingeführt: using. Dieses Schlüsselwort erleichtert das Ressourcenmanagement erheblich und stellt sicher, dass Ressourcen ordnungsgemäß freigegeben werden, wenn sie nicht mehr benötigt werden. Dieser Artikel soll die wichtigsten Aspekte von einem Ressourcenmanagement aufzeigen sowie das neue Feature kurz vorstellen.

Warum ist das Ressourcenmanagement wichtig?

In der Programmierung ist es unerlässlich, Ressourcen wie Dateihandles, Datenbankverbindungen und andere Objekte, die externe Ressourcen oder Systemressourcen verwenden, ordnungsgemäß zu verwalten. Wenn diese Ressourcen nicht korrekt freigegeben werden, kann dies zu Speicherlecks, Systeminstabilität oder anderen unerwünschten Nebenwirkungen führen.

Manuelles Verwalten von Ressourcen ohne das “using”-Feature

Bevor das using-Feature eingeführt wurde, mussten Entwickler manuell sicherstellen, dass Ressourcen ordnungsgemäß freigegeben wurden. Dafür gibt es verschiedene Wege. Die am weitesten verbreiteteste Methode war die Implementierung einer dispose-Methode. Diese muss manuell aufgerufen werden, wenn das Objekt nicht länger benötigt wird.

Eine teilweise Automatisierung ist mit Hilfe des in-Operators möglich. So kann unter Verwendung einer benutzerdefinierten Typeguard-Funktion festgestellt werden, ob ein Objekt die dispose-Methode implementiert. Ferner ist so ein typesicherer Zugiff möglich.

// Definition des IDisposable-Interfaces
interface IDisposable {
  dispose: () => void;
}

// Eine benutzerdefinierte Typeguard-Funktion
function isDisposable(obj: any): obj is IDisposable {
  return "dispose" in obj;
}

// Eine Klasse, die das IDisposable-Interface implementiert
class MyResource implements IDisposable {
  // ... andere Methoden und Eigenschaften ...

  // Implementierung der dispose-Methode
  dispose() {
    console.log("Ressource wurde freigegeben.");
    // Hier können weitere Aufräumarbeiten durchgeführt werden
  }
}

// Verwendung des MyResource-Objekts
const resource = new MyResource();

// ... Verwendung der Ressource ...

// Überprüfung, ob die Ressource eine dispose-Methode hat und Aufruf der Methode
if (isDisposable(resource)) {
  resource.dispose();
}

In obigen Beispiel wird eine Ressource erstellt und dann manuell freigegeben.

Das neue “using”-Feature

Mit dem using-Schlüsselwort wird eine neue Möglichkeit in JavaScript / TypeScript eingeführt, um Ressourcen automatisch freizugeben, sobald diese den Gültigkeitsbereich der deklarierten Variablen Verlassen. TypeScript 5.2 implementiert diesen Vorschlag der unter TC39 proposal aufgenommen wurde und sich zur Zeit in Stage 3 befindet. Das bedeutet, dass er von den ersten Anwendern getestet werden kann.

Um ein natives using zu realisieren, wurde eine Konstante mit dem neues Symbol Symbol.dispose eingeführt. Dieses ist der Schlüssel unter dem die dispose-Methode abzulegen ist, die automatisch aufgerufen werden soll. Das folgende Beispiel zeigt eine Funktion, die eine Ressource erstellt, die später mit Hilfe von using verwendet werden soll.

Wird die Variable mit using anstelle mit let oder const erstellt wird diese Funktion automatisch aufgerufen, sobald der Gültigkeitsbereich der variablen verlassen wird. Wie bei let und const wirkt using innerhalb eines Block-Scopes .

{
  const CreateObject = () => {
    return {
        // Andere Member und Methoden

        [Symbol.dispose]: () => {
        // hier können ressourcen wie entladen bzw. zurück gegeben werden  
        console.log('Diese Funktion wird automatisch aufgerufen.');
        }
    };
  }

  using myObject = CreateObject();
  // 'Diese Funktion wird automatisch aufgerufen', sobald die Ressource den Gültigkeitsbereich verlässt
}

Das “using”-Feature mit async

Das neue Feature kann nicht nur synchrone Ressourcen freigeben, es ist auch möglich asynchrone Ressourcen freizugeben, z.B Datenbankverbindungen. Dies ist der Fall, wenn eine Ressource einen asynchronen Vorgang benötigt, um bereit gestellt zu werden. Dafür gibt es ein anderes Symbol: Symbol.asyncDispose. Wie auch bei der synchronen Variante wird die Funktion zur Freigabe der Ressourcen automatisch ausgerufen, sobald der Block-Scope verlassen wird.

// Deklaration
const getConnection = async () => {
  const connection = await getDb();
  return {
    connection,
    [Symbol.asyncDispose]: async () => {
      await connection.close();
    },
  };
};

// Verwendung
{
  await using db = await getConnection();
  // Arbeiten mit db.connection
} // Automatisch geschlossen!

Zusammenfassung

Das using-Feature in TypeScript 5.2 ist ein interessanter Schritt nach vorne im Ressourcenmanagement. Es ermöglicht Entwicklern, Ressourcen effizienter und sicherer zu verwalten, ohne sich manuell um das Freigeben von Ressourcen kümmern zu müssen. Dies führt zu saubererem, wartbarerem und zuverlässigerem Code.