Skip to content

fix(types,parser): TS conformance Track-1 continuation — symbol member modeling + ParseError cluster#1259

Merged
nickna merged 4 commits into
mainfrom
worktree-epic-99
Jul 5, 2026
Merged

fix(types,parser): TS conformance Track-1 continuation — symbol member modeling + ParseError cluster#1259
nickna merged 4 commits into
mainfrom
worktree-epic-99

Conversation

@nickna

@nickna nickna commented Jul 5, 2026

Copy link
Copy Markdown
Owner

Summary

Continuation of epic #99 / #80 Track-1 (TS conformance). Picks up where PR #1258 left off, per the follow-up comment on #99.

Round 1: symbol member modeling + ParseError cluster

  • Parser: extends feat: parse dense .d.ts — es5/es2015.core lib files now parse (#99 Phase A) #168's type-position hardening to value/class position — computed well-known-symbol keys ([Symbol.iterator], [Symbol()], ...) on class fields, interface members, and inline object-type members now allow an omitted type annotation / return type (implicit any), matching identifier-keyed members. Also accepts Symbol (and other contextual keywords) as a namespace name and in typeof-type-position dotted names.
  • Checker: object literals and interfaces were collapsing every computed well-known-symbol member into one merged symbol index signature, losing per-symbol precision — this produced spurious errors reading/calling/writing a specific symbol member, and spurious errors assigning an object literal with several distinct symbol members to a matching interface. Each well-known-symbol member is now modeled under its canonical @@name (matching how interfaces/classes already do), with the index get/set paths checking that named member first.
  • Three smaller bugs found by the same test cluster: interface string-index-signature compatibility (TS2411) wrongly flagged symbol-keyed members; declare const x: unique symbol; wrongly required a Symbol() initializer; typeof-narrowing didn't recognize numeric/string enum members, and a union typeof-guard with no matching member defined the narrowed binding as a literal null type instead of never (surfaced as a bogus "undefined variable").

Round 2: the remaining ParseError long tail

Seven unrelated, independently-scoped parser gaps found while clearing what was left of the ParseError bucket:

  • Object-type/interface members separated only by a newline now use the same ASI fallback as top-level interface members.
  • A parenthesized member/index expression is a valid assignment target for =, compound, and logical-assignment operators ((a.b) &&= v) — unwrap parens before dispatch.
  • async is a contextual keyword: only commit to parsing an async function/arrow when it's immediately followed by function/</(; otherwise it's a plain identifier (if (async)).
  • import.meta used as a statement was routed to the static import-declaration parser, which only excluded dynamic-import's import(, not import..
  • export { x as y } (bare specifier list) inside declare global/declare module bodies was unhandled.
  • export * as ns from './mod' (ES2020 namespace re-export) wasn't recognized.
  • An untagged template with an invalid escape sequence is a real but recoverable syntax error (TS1125) — the parser now substitutes an empty string and records the offending line instead of aborting the whole file's parse; the checker reports TS1125 there. Tagged templates are unaffected.

Result: TS conformance subset baseline 188 → 207 Pass, 24 → 0 ParseError, 0 regressions. The ParseError bucket for this subset is now empty.

Test plan

nickna added 4 commits July 5, 2026 13:59
…osition

Extends #168's type-position parser hardening past type position: class
fields/interface members/inline-object-type members with a computed key
([Symbol.iterator], [Symbol()], ...) now allow an omitted type annotation
(implicit any, matching identifier-keyed members) instead of unconditionally
requiring ':'. Method/call/construct signatures similarly allow an omitted
return type. Also accepts 'Symbol' and other contextual keywords as a
namespace name and in typeof-type-position dotted names, both previously
routed through a bare IDENTIFIER-only Consume.

Flips 17 of 24 outstanding TS conformance ParseErrors (symbolProperty*/
symbolType* cluster) to Pass/Fail.
…merged index

Object literals and interfaces collapsed every computed well-known-symbol
member ([Symbol.iterator], [Symbol.toStringTag], [Symbol.toPrimitive], ...)
into a single merged symbol index signature, losing per-symbol precision.
This produced spurious TS7053s reading/calling a specific symbol member,
spurious TS2741s assigning an object literal with several distinct
symbol members to an interface, and a spurious TS2322 writing through a
symbol key that has its own accessor. CheckObject now records each
well-known-symbol member under its canonical "@@name" (matching how
interfaces/classes already model them); the index get/set paths check for
that named member before falling back to the merged signature.

Also, three smaller fixes surfaced by the same test cluster:
- Interface string-index-signature compatibility (TS2411) no longer flags
  computed well-known-symbol members — a symbol key can never collide with
  a string index at runtime.
- `declare const x: unique symbol;` (ambient, no initializer) no longer
  hits the "must be initialized with Symbol()" check, which only makes
  sense for a real initializer; gated on a new Stmt.Var.IsDeclare flag
  (not a null-initializer heuristic, which also matches non-ambient
  `let x: unique symbol;` and would wrongly let that through too).
- typeof-narrowing now recognizes numeric/string enum members as matching
  "number"/"string" respectively; a union typeof-guard with no matching
  member now narrows to `never` instead of defining the binding as a
  literal null type (which read back as "undefined variable").
131 -> 203 Pass, 24 -> 7 ParseError, 0 regressions.
@nickna nickna merged commit da0e0e4 into main Jul 5, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant