Announcing: A Free Book, A New Course, A Huge Price Cut...
It's a massive ship day. We're launching a free TypeScript book, new course, giveaway, price cut, and sale.
TypeScript 5.2 introduces a new keyword - using
- that you can use to dispose of anything with a Symbol.dispose
function when it leaves scope.
{
const getResource = () => {
return {
[Symbol.dispose]: () => {
console.log('Hooray!')
}
}
}
using resource = getResource();
} // 'Hooray!' logged to console
This is based on the TC39 proposal, which recently reached Stage 3 (out of 4) in its progress to JavaScript. This means that it's ready to be tested by early adopters.
using
will be extremely useful for managing resources like file handles, database connections, and more.
Symbol.dispose
Symbol.dispose
is a new global symbol in JavaScript. Anything with a function assigned to Symbol.dispose
will be considered a 'resource' - "an object with a specific lifetime" - and can be used with the using
keyword.
const resource = {
[Symbol.dispose]: () => {
console.log("Hooray!");
},
};
await using
You can also use Symbol.asyncDispose
and await using
to handle resources which need to be disposed asynchronously.
const getResource = () => ({
[Symbol.asyncDispose]: async () => {
await someAsyncFunc();
},
});
{
await using resource = getResource();
}
This will await the Symbol.asyncDispose
function before continuing.
This will be useful for resources such as database connections, where you want to ensure that the connection is closed before the program continues.
Accessing the file system via file handlers in node could be a lot easier with using
.
Without using
:
import { open } from "node:fs/promises";
let filehandle;
try {
filehandle = await open("thefile.txt", "r");
} finally {
await filehandle?.close();
}
With using
:
import { open } from "node:fs/promises";
const getFileHandle = async (path: string) => {
const filehandle = await open(path, "r");
return {
filehandle,
[Symbol.asyncDispose]: async () => {
await filehandle.close();
},
};
};
{
await using file = await getFileHandle("thefile.txt");
// Do stuff with file.filehandle
} // Automatically disposed!
Managing database connections is a common use case for using
in C#.
Without using
:
const connection = await getDb();
try {
// Do stuff with connection
} finally {
await connection.close();
}
With using
:
const getConnection = async () => {
const connection = await getDb();
return {
connection,
[Symbol.asyncDispose]: async () => {
await connection.close();
},
};
};
{
await using db = await getConnection();
// Do stuff with db.connection
} // Automatically closed!
Share this article with your friends
It's a massive ship day. We're launching a free TypeScript book, new course, giveaway, price cut, and sale.
Learn why the order you specify object properties in TypeScript matters and how it can affect type inference in your functions.
Learn how to use corepack
to configure package managers in Node.js projects, ensuring you always use the correct one.
Learn how to strongly type process.env in TypeScript by either augmenting global type or validating it at runtime with t3-env.
Discover when it's appropriate to use TypeScript's any
type despite its risks. Learn about legitimate cases where any
is necessary.
Learn why TypeScript's types don't exist at runtime. Discover how TypeScript compiles down to JavaScript and how it differs from other strongly-typed languages.