swc-project/swc · error · TypeError

Object expected.

Error message

Object expected.

What it means

`_ts_add_disposable_resource` backs TypeScript `using`/`await using` declarations that SWC downlevels for old targets. Explicit resource management only accepts objects, functions, `null`, and `undefined`; passing a primitive triggers `TypeError("Object expected.")` because primitives cannot carry `[Symbol.dispose]`.

Source

Thrown at crates/swc_ecma_transforms_base/src/helpers/generated/_ts_add_disposable_resource.rs:13

// This file is generated by `cargo codegen helpers`. DO NOT MODIFY.

use super::{HelperDef, HelperName};

pub const DEF: HelperDef = HelperDef {
    name: HelperName::ts_add_disposable_resource,
    local: "_ts_add_disposable_resource",
    import_path: "@swc/helpers/_/_ts_add_disposable_resource",
    #[cfg(feature = "inline-helpers")]
    source: r#"function _ts_add_disposable_resource(env, value, async) {
    if (value !== null && value !== void 0) {
        if (typeof value !== "object" && typeof value !== "function") {
            throw new TypeError("Object expected.");
        }
        var dispose, inner;
        if (async) {
            if (!Symbol.asyncDispose) {
                throw new TypeError("Symbol.asyncDispose is not defined.");
            }
            dispose = value[Symbol.asyncDispose];
        }
        if (dispose === void 0) {
            if (!Symbol.dispose) {
                throw new TypeError("Symbol.dispose is not defined.");
            }
            dispose = value[Symbol.dispose];
            if (async) {
                inner = dispose;
            }
        }
        if (typeof dispose !== "function") {

View on GitHub (pinned to 5176682b65)

Solutions

  1. Only use `using`/`await using` with disposable resources — objects or functions exposing `[Symbol.dispose]`/`[Symbol.asyncDispose]` — plus `null`/`undefined`.
  2. If you need cleanup around a primitive, wrap it: `using box = { [Symbol.dispose]: () => cleanup(), value };`.
  3. Use plain `try/finally` for primitives instead of `using`.

Example fix

// before
function run() {
  using handle = getHandle(); // returns 42 for some inputs
  // TypeError: Object expected.
}

// after
function run() {
  const handle = getHandle();
  if (typeof handle === 'number') { /* primitive path, no using */ return; }
  using h = handle; // now provably an object
}
Defensive patterns

Strategy: type-guard

Validate before calling

// Mirror the helper's own rule before the `using` statement.
const isUsableResource = (v) =>
  v === null || v === undefined || typeof v === 'object' || typeof v === 'function';
const res = acquire();
if (!isUsableResource(res)) {
  throw new TypeError(`using requires an object/function/null/undefined, got ${typeof res}`);
}
using r = res;

Type guard

type UsableResource = Disposable | AsyncDisposable | null | undefined;
const isUsableResource = (v: unknown): v is UsableResource =>
  v == null || typeof v === 'object' || typeof v === 'function';

Prevention

When it happens

Trigger: `using x = 42;`, `using s = 'text';`, or an acquire function that conditionally returns a primitive, compiled with `using` declarations for a target without native support (Node < 20 / ES2022-).

Common situations: Trying to abuse `using` as a generic scope-exit hook for primitives; a `getHandle()` whose return type union includes primitives; TS 5.2+ code compiled for older runtimes.

Related errors


AI-assisted analysis of swc-project/swc@5176682b65 (2026-08-17). Data as JSON: /api/errors/6be7610c330c2d53. Report an issue: GitHub.