🔎 Search Terms
CompilerOptions, JsxEmit, ModuleResolutionKind, esModuleInterop, API, unstable/sync
🕗 Version & Regression Information
- This changed between versions 6.0 and 7.0 — TypeScript 6's public API exported the option enums and declared every compiler option.
- Verified on 7.0.2 and on typescript@next (7.1.0-dev.20260827.1); both behave the same.
Related: #63910 (TypeFormatFlags enum missing) is the same class of problem and has been fixed — TypeFormatFlags is now reachable, while the two enums below are not.
💻 Code
The API's CompilerOptions names two enums that no export path provides:
// dist/api/proto.generated.d.ts (7.1-dev); dist/api/compilerOptions.d.ts (7.0.2)
jsx?: JsxEmit;
moduleResolution?: ModuleResolutionKind;
Neither is exported from any of the package's twelve export paths:
for (const p of ["unstable/sync", "unstable/async", "unstable/fs", "unstable/proto",
"unstable/ast", "unstable/ast/is", "unstable/ast/factory",
"unstable/ast/utils", "unstable/ast/scanner", "unstable/ast/visitor",
"unstable/ast/clone"]) {
const m = await import(`typescript/${p}`);
for (const k of ["JsxEmit", "ModuleResolutionKind", "TypeFormatFlags"]) {
if (m[k] !== undefined) console.log(p, k);
}
}
// prints only: unstable/sync TypeFormatFlags
They exist in the package, but only under the internal #enums/* subpath:
node_modules/typescript/dist/enums/jsxEmit.enum.js
node_modules/typescript/dist/enums/moduleResolutionKind.enum.js
Separately, two options tsc accepts do not appear in CompilerOptions at all:
$ grep -rc "esModuleInterop" node_modules/typescript/dist/
0
🙁 Actual behavior
A typed CompilerOptions cannot be written:
- jsx and moduleResolution can only be set by importing enums that are unreachable, so the field is unusable except via as any or a hand-copied numeric literal.
- esModuleInterop and allowSyntheticDefaultImports are rejected as unknown properties, though the compiler honours them.
🙂 Expected behavior
Every enum a public type references is exported from a public path, and CompilerOptions covers the options the compiler accepts — so an API consumer can build one without casts.
Additional information about the issue
Found while porting a lossless-syntax tool (OpenRewrite's JavaScript/TypeScript parser) from the TypeScript 6 API to 7. The workaround is to bypass the type entirely and write the options as tsconfig JSON with string values ("jsx": "preserve", "moduleResolution": "bundler"), which does work — the gap is only in the typed surface.
I have filed the two together because they look like one cause: CompilerOptions being generated from, or hand-mirrored against, an incomplete source. Happy to split them if that is not the case.
🔎 Search Terms
CompilerOptions, JsxEmit, ModuleResolutionKind, esModuleInterop, API, unstable/sync
🕗 Version & Regression Information
Related: #63910 (TypeFormatFlags enum missing) is the same class of problem and has been fixed — TypeFormatFlags is now reachable, while the two enums below are not.
💻 Code
The API's CompilerOptions names two enums that no export path provides:
Neither is exported from any of the package's twelve export paths:
They exist in the package, but only under the internal #enums/* subpath:
Separately, two options tsc accepts do not appear in CompilerOptions at all:
🙁 Actual behavior
A typed CompilerOptions cannot be written:
🙂 Expected behavior
Every enum a public type references is exported from a public path, and CompilerOptions covers the options the compiler accepts — so an API consumer can build one without casts.
Additional information about the issue
Found while porting a lossless-syntax tool (OpenRewrite's JavaScript/TypeScript parser) from the TypeScript 6 API to 7. The workaround is to bypass the type entirely and write the options as tsconfig JSON with string values ("jsx": "preserve", "moduleResolution": "bundler"), which does work — the gap is only in the typed surface.
I have filed the two together because they look like one cause: CompilerOptions being generated from, or hand-mirrored against, an incomplete source. Happy to split them if that is not the case.