Files
oxc-project__oxc/tasks/coverage/misc/fail/ts-unerasable-satisfies.ts
Boshen 17e7cf3ce4 fix(parser): disallow unerasable as/satisfies assertions (#22986)
Port of [microsoft/typescript-go#4192](https://github.com/microsoft/typescript-go/pull/4192), which fixes [microsoft/TypeScript#63527](https://github.com/microsoft/TypeScript/issues/63527).

## Problem

`as`/`satisfies` are supposed to be erasable without changing runtime semantics. But for an expression of the form `a ## b as T $$ c`, where `##` has *lower* precedence than `$$`, erasing the assertion silently changes the parse:

```ts
const x = 1 + 1 as number * 2;
```

This parses as `((1 + 1) as number) * 2` (= `4`), but textually erasing `as number` yields `1 + 1 * 2` (= `3`). TypeScript now rejects such constructs as a syntax error, forcing explicit parentheses.

## Change

In `parse_binary_expression_rest`, after parsing an `as`/`satisfies` type, stop parsing if the following operator binds tighter than the operator that produced the running left-hand operand. This leaves the higher-precedence operator dangling and surfaces as a parse error.

A chained `a as T as U` keeps referring back to the original operator's precedence (the tracked precedence is intentionally not updated while consuming `as`/`satisfies`), so `1 + 1 as any as number * 2` is rejected too.

## Behavior

| Expression | Result |
| --- | --- |
| `1 as number * 2` | ok |
| `1 * 1 as number + 2` | ok (`+` does not bind tighter than `*`) |
| `1 + 1 as number * 2` | **error** |
| `1 + 1 as any as number * 2` | **error** |
| `1 >> 1 as number + 2` | **error** |
| `(1 + 1 as number) * 2` | ok |

`satisfies` behaves identically to `as`.

## Tests

Added `misc` coverage fixtures mirroring the upstream test matrix: `pass/ts-erasable-as-satisfies.ts` for the erasable cases and `fail/ts-unerasable-{as,as-chained,satisfies}.ts` for the rejected ones. Full conformance (test262 / babel / typescript) shows zero regressions.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-06-05 13:10:42 +00:00

5 lines
201 B
TypeScript

// https://github.com/microsoft/TypeScript/issues/63527
// Same rule as `as`: erasing `satisfies number` would let `*` re-associate, so this
// is a syntax error.
const x = 1 + 1 satisfies number * 2;