Synchronous resource management
Close file handles, sockets, or other synchronous resources automatically when a block ends.
TypeScript · Const
The using declaration creates a fixed binding like const and automatically calls the resource's Symbol.dispose method when its scope ends. Cleanup also occurs on early exits and follows last-in-first-out order.
A using declaration creates a fixed binding whose resource is automatically disposed when control leaves its containing scope. Cleanup happens at scope exit, including early returns or thrown errors, and multiple resources are released in last-in-first-out order.
using variable = expression;Symbol.dispose ??= Symbol("Symbol.dispose");
class FileHandle {
[Symbol.dispose]() {
console.log("closed");
}
}
{
using file = new FileHandle();
console.log("working");
}The binding is fixed like const, and leaving the block invokes the object's Symbol.dispose method.
Close file handles, sockets, or other synchronous resources automatically when a block ends.
Ensure cleanup runs when functions return early or throw errors.
Release nested resources in reverse acquisition order.
A using declaration is similar to const because it creates a fixed binding, but it additionally arranges for the bound object's Symbol.dispose method to run when the scope ends. This makes resource cleanup automatic.
Follow-up: What happens if the scope exits through an exception? Cleanup still runs before the exception propagates.
Resources are disposed at the end of their containing scope and before an early return or thrown error. Multiple using declarations are cleaned up in first-in-last-out order, like a stack.
Follow-up: Why is reverse order useful? It lets later-created resources be released before resources they may depend on.
The feature may need polyfills for Symbol.dispose and Symbol.asyncDispose, along with other disposable-stack and suppressed-error types when those APIs are used. The compiler target should be es2022 or lower, with an appropriate disposable lib.
Follow-up: What is the minimal polyfill requirement for only using and await using? The built-in disposal symbols are generally sufficient.
await usingSymbol.disposeSymbol.asyncDisposeDisposableStackAsyncDisposableStackSuppressedError