Rulebearing Playground Coverage Schemas GitHub

ADR-0064: A .ts file is parsed as TypeScript when the tsconfig sets jsx

Context

When tsPreCompilationDeps is not true and the parser is neither tsc nor swc, dependency-cruiser compiles each TypeScript file with typescript.transpileModule and reads the JavaScript with acorn. It passes the tsconfig's compiler options but no file name (src/extract/transpile/typescript-wrap.mjs). TypeScript then names the input module.tsx when jsx is set, and module.ts otherwise. So a tsconfig that sets jsx makes every .ts file parse as TSX.

TSX syntax is not a superset of TypeScript syntax. A generic arrow function (<T>(x: T): T => x) and an angle-bracket type assertion (<Foo>bar) are both valid in a .ts file and both open a JSX element in a .tsx file. tsc reports the parse error and recovers. Whatever the recovery takes as JSX text is no longer code, so an import whose only use falls inside it is elided as unused. The edge then disappears from the cruise result.

Which imports survive depends on where tsc's recovery resynchronises. The fixture crates/rb-extract-ts/tests/options/ts-jsx imports ./a, declares a generic arrow, then imports ./b and uses both. dependency-cruiser 18.2.0 with TypeScript 6.0.3 keeps src/b.ts and drops src/a.ts; without jsx it keeps both. Wave 1 found the case on langfuse with tsPreCompilationDeps: false: 14 edges in 6 files. That is not the oracle's configuration, so gate 1's layer 5 has never compared it.

Rulebearing parses with oxc (ADR-0012) and takes a file's syntax from its extension. It reads the fixture's .ts file as TypeScript in both configurations and reports both edges.

Decision

Rulebearing parses a .ts, .mts or .cts file as TypeScript whatever the tsconfig's jsx says. It does not reproduce upstream's TSX misparse. The difference is a permanent divergence in conformance/divergences.md, in a section layer 5 does not read, because no oracle runs the configuration.

crates/rb-extract-ts/tests/options.rs (a_ts_file_is_typescript_whatever_the_tsconfig_jsx) pins Rulebearing's answer. Its doc comment records upstream's answer on the same fixture.

Consequences

Alternatives considered

Option Why not
Parse a .ts file as TSX when jsx is set, as upstream does oxc's recovery is not tsc's. The two would drop different imports, so the output would still differ from upstream, and now it would also be wrong about the source.
Reproduce tsc's error recovery It means re-implementing tsc's parser failure modes, version by version, to drop edges that exist.
Warn when a .ts file holds syntax that TSX reads differently It would need a second parse of every .ts file as TSX on every run, to report an upstream defect that the user can avoid by setting tsPreCompilationDeps: true. It can be added later without changing this decision.
Exit 3 under the configuration The configuration is valid and Rulebearing answers it correctly. Refusing it would block every repository that sets jsx for its .tsx files.