rollup/rollup · error

not implemented: Cannot convert Expr::TsAs

Error message

not implemented: Cannot convert Expr::TsAs

What it means

convert_expression (converter.rs:322) has an unimplemented! arm at line 418 for Expr::TsAs. TsAs is TypeScript's `as` assertion `value as Type`, the most common TS cast form. The native parser is TS-tolerant (Syntax::Es, lib.rs:23) so SWC produces TsAs, but the buffer format cannot represent it and the converter panics; this is thrown to JS as a Rollup parse error.

Source

Thrown at rust/parse_ast/src/convert_ast/converter.rs:418

      Expr::Update(update_expression) => {
        self.store_update_expression(update_expression);
      }
      Expr::Yield(yield_expression) => {
        self.store_yield_expression(yield_expression);
      }
      Expr::JSXMember(_) => unimplemented!("Cannot convert Expr::JSXMember"),
      Expr::JSXNamespacedName(_) => unimplemented!("Cannot convert Expr::JSXNamespacedName"),
      Expr::JSXEmpty(_) => unimplemented!("Cannot convert Expr::JSXEmpty"),
      Expr::JSXElement(jsx_element) => {
        self.store_jsx_element(jsx_element);
      }
      Expr::JSXFragment(jsx_fragment) => {
        self.store_jsx_fragment(jsx_fragment);
      }
      Expr::TsTypeAssertion(_) => unimplemented!("Cannot convert Expr::TsTypeAssertion"),
      Expr::TsConstAssertion(_) => unimplemented!("Cannot convert Expr::TsConstAssertion"),
      Expr::TsNonNull(_) => unimplemented!("Cannot convert Expr::TsNonNull"),
      Expr::TsAs(_) => unimplemented!("Cannot convert Expr::TsAs"),
      Expr::TsInstantiation(_) => unimplemented!("Cannot convert Expr::TsInstantiation"),
      Expr::TsSatisfies(_) => unimplemented!("Cannot convert Expr::TsSatisfies"),
      Expr::Invalid(_) => unimplemented!("Cannot convert Expr::Invalid"),
    }
  }

  pub(crate) fn convert_expression_or_spread(&mut self, expression_or_spread: &ExprOrSpread) {
    match expression_or_spread.spread {
      Some(spread_span) => self.store_spread_element(&spread_span, &expression_or_spread.expr),
      None => {
        self.convert_expression(&expression_or_spread.expr);
      }
    }
  }

  pub(crate) fn convert_for_head(&mut self, for_head: &ForHead) {
    match for_head {
      ForHead::VarDecl(variable_declaration) => {

View on GitHub (pinned to ddc4ffab62)

Solutions

  1. Add a TypeScript transform plugin (@rollup/plugin-typescript, @rollup/plugin-swc, or rollup-plugin-esbuild) so `as` is removed before the native parser runs.
  2. If only one module is affected, pre-transpile that module to JS and import the built file.
  3. As a last resort rewrite the assertion away, though this is impractical across a real TS codebase.

Example fix

// before
const len = (arr as number[]).length;

// after (post TS strip)
const len = arr.length;
Defensive patterns

Strategy: validation

Validate before calling

// Detect TS `as` assertions.
function hasTsAs(src) {
  return /\)\s*as\s+[A-Z]|\bas\s+(const|unknown|[A-Z])/.test(src);
}
if (hasTsAs(code)) {
  throw new Error('Source uses `as` assertions; strip TS with a transform plugin.');
}

Try / catch

try {
  await rollup({ input });
} catch (err) {
  if (String(err.message).includes('Expr::TsAs')) {
    throw new Error('Raw TS `as` assertion reached the native parser; add a TS plugin.');
  }
  throw err;
}

Prevention

When it happens

Trigger: Source fed to Rollup's native parser contains `x as T`, `obj as unknown as T`, or `fn() as Promise<X>`. The Expr::TsAs node has no store arm in convert_expression. This is one of the most frequently hit arms for raw TypeScript bundles.

Common situations: Bundling .ts/.tsx source without a transform plugin that strips types. `.d.ts`-adjacent code or type tests copied into bundled source. Migration from tsc-only builds to Rollup without adding a TS plugin.

Related errors


AI-assisted analysis of rollup/rollup@ddc4ffab62 (2026-08-03). Data as JSON: /data/errors/493e94d6449874d5.json. Report an issue: GitHub.