[Answered] How do I enable Explicit Resource Management in a new Ember app?

For anyone curious about the new Explicit Resource Management features coming soon and supported by latest versions of TypeScript here are some steps to enable it in your Ember apps today!

Demo

Steps

  1. install dependencies
  2. add babel plugin to ember-cli-build.js to enable the plugin
  3. add import to app/app.ts to enable the polyfill

Dependencies

npm install -D @babel/plugin-proposal-explicit-resource-management disposablestack

Enable plugin

In ember-cli-build.js add the following

--- a/ember-cli-babel.js	2025-01-16 21:15:53.949082700 -0500
+++ b/ember-cli-babel.js	2025-01-16 21:16:32.965648714 -0500
@@ -6,6 +6,12 @@
   const app = new EmberApp(defaults, {
     'ember-cli-babel': { enableTypeScriptTransform: true },
 
+    babel: {
+      plugins: [
+        '@babel/plugin-proposal-explicit-resource-management',
+      ],
+    },
+
     // Add options here
   });
 

Enable polyfill

Add this to the top of app/app.ts:

import 'disposablestack/auto';

Using

You can now use the using keyword as well as Symbol.dispose and DisposableStack. Also all the Async variants of that as well.

Here is an example that handles persistent storage via localStorage.

import Service from '@ember/service';

class PersistentStore<T = unknown> {
  data: T
  constructor(readonly key: string) {
    this.data = JSON.parse(localStorage.getItem(key) ?? '{}') as T;
  }
  [Symbol.dispose]() {
    localStorage.setItem(this.key, JSON.stringify(this.data));
  }
}

interface FooBarData {
  foo?: string;
  bar?: string;
}

const FOO_BAR_KEY = 'my-fancy-foo-bar-key';

export default class FooBar extends Service {
  updateFoo(newValue: string) {
    using store = new PersitententStore<FooBarData>(FOO_BAR_KEY);
    store.data.foo = newValue;
  }

  updateBar(newValue: string) {
    using store = new PersitententStore<FooBarData>(FOO_BAR_KEY);
    store.data.bar = newValue;
  }
}
2 Likes