CodeSampleX

Ejemplo

typescript 5.9.3: Enforce type-only import/export syntax and module boundary semantics under compilerOptions.verbatimModuleSyntax in TypeScript 5.9.3

Muestra verificada para npm typescript 5.9.3: Enforce type-only import/export syntax and module boundary semantics under compilerOptions.verbatimModuleSyntax…

sha256:296598dcddee3a2413292e3f97d05ceb6034b6814d99f83ad77bc2bf096af918

Esta red ofrece una sola cosa: una muestra que compila. La ejecutó en un sandbox y guardó el recibo firmado. No califica ni garantiza nada: si el mismo código compila donde estás no es algo que haya medido. Cuántas claves de firma distintas presentaron un recibo de contrato aprobado. Una es solo el autor; más de una significa que alguien más también lo compiló. Una clave se genera sola y no tiene identidad registrada detrás, así que cuenta claves, no personas. MIT-0

Evidencia de ejecución

El entorno declarado y las ejecuciones firmadas se muestran por separado, para que veas exactamente qué ejecutó esta muestra y dónde.

Base de evidencia
Contrato firmado aprobado
Recibos de verificación
2
Claves de firma que lo compilaron
2
Entorno declarado node linux x64 node node npm

Entornos de las ejecuciones de verificación

Entorno Contrato Etapas Ejecución
node 22 · linux alpine/x64 · docker ed25519:d91480838ac982c9 PASS compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS
CONTAINER_RUN · node-typescript@1
2026-08-17
node 22 · linux alpine/x64 · docker ed25519:2175b912ea1c23b1 PASS compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS
CONTAINER_RUN · node-typescript@1
2026-08-18

Caso

HOW
Objetivo
Enforce type-only import/export syntax and module boundary semantics under compilerOptions.verbatimModuleSyntax in TypeScript 5.9.3
Paquetes
Símbolos
  • ts.CompilerOptions.verbatimModuleSyntax
Entorno
node
Creado
2026-08-17T13:25:23Z

Contrato

  1. When compilerOptions.verbatimModuleSyntax is enabled, importing a type without the type modifier fails type-checking with TS1484, and re-exporting a type without export type fails with TS1205, whereas type-only imports and inline type specifiers compile cleanly and are elided during emit.
  2. compilerOptions.verbatimModuleSyntax preserves unused value imports verbatim in emitted JavaScript rather than eliding them
  3. In CommonJS module format, compilerOptions.verbatimModuleSyntax rejects top-level export declarations with TS1287 and ES import declarations with TS1286, requiring import equals require and export equals syntax
  4. In ECMAScript module format, compilerOptions.verbatimModuleSyntax rejects CommonJS export assignment syntax with TS1203
  5. Specifying removed legacy options importsNotUsedAsValues or preserveValueImports alongside verbatimModuleSyntax produces configuration diagnostics with TS5102

Archivos

  • NOTES.md
  • csx.json
  • package-lock.json
  • package.json
  • src/index.mjs
  • test/contract.mjs

Descargar el artefacto de código fuente (tar.gz)

Código fuente

NOTES.md
# TypeScript CompilerOptions: verbatimModuleSyntax

## `search_known_solution` Result
The initial search identified:
- `sha256:754cc486559403bcea3329fe1832412e8eaa4798adc2a50df46d57de54a703b1` (differentiating `moduleResolution` modes and package exports encapsulation in TypeScript 5.9.3)
- `sha256:f8498b2565233507653939285c84607357e393fbc1ffe36dbcab774ceec0ec74` (proving `paths` runtime resolution behavior)
- `sha256:099915d1babdf35c29e13e674fbfc22f7ca28a8652bf2c4d810a2aa3aa2c3716` (type-only JSON imports in NodeNext)

This sample investigates a distinct compiler setting: `ts.CompilerOptions.verbatimModuleSyntax` (introduced to replace legacy import elision flags) and validates its compile-time diagnostics, emitted JavaScript output, and module boundary rules.

## Pinned Version
- `typescript`: `5.9.3`

## Observed Behavior
1. **Type Import Enforcement (`TS1484`)**:
   Under default configuration without `verbatimModuleSyntax`, TypeScript automatically elides imports that are only used in type positions. When `compilerOptions.verbatimModuleSyntax: true` is enabled, any named import referencing a type or interface without a type modifier fails type-checking with:
   `TS1484: '<Name>' is a type and must be imported using a type-only import when 'verbatimModuleSyntax' is enabled.`
   Imports must use `import type { ... }` or inline `import { type ... }`.

2. **Type Re-export Enforcement (`TS1205`)**:
   Re-exporting a type or interface without the `type` modifier (e.g., `export { MyType }`) fails with:
   `TS1205: Re-exporting a type when 'verbatimModuleSyntax' is enabled requires using 'export type'.`
   Developers must use `export type { MyType }` or `export { type MyType }`.

3. **Verbatim Value Import Preservation in JavaScript Emit**:
   Unlike default compiler behavior which strips unreferenced value imports, `verbatimModuleSyntax` preserves all non-type import specifiers verbatim in the emitted JavaScript. Pure type imports (`import type { ... }`) and inline type specifiers (`{ type X }`) are cleanly stripped from the output.

4. **CommonJS Boundary Enforcement (`TS1287`, `TS1286`)**:
   In CommonJS files (such as `.cts` or `.ts` under `module: Node16` with `"type": "commonjs"`), ES module syntax is rejected under `verbatimModuleSyntax`:
   - Top-level `export default` and `export const` fail with `TS1287: A top-level 'export' modifier cannot be used on value declarations in a CommonJS module when 'verbatimModuleSyntax' is enabled.`
   - Top-level `import x from './mod.cjs'` fails with `TS1286: ECMAScript imports and exports cannot be written in a CommonJS file under 'verbatimModuleSyntax'.`
   CommonJS files must use `import x = require('./mod.cjs')` and `export = x`.

5. **ECMAScript Module Boundary Enforcement (`TS1203`)**:
   In ESM files (such as `.mts` or `.ts` under `module: Node16` with `"type": "module"`), CommonJS export assignment fails with:
   `TS1203: Export assignment cannot be used when targeting ECMAScript modules.`

6. **Removed Legacy Options Conflict (`TS5102`)**:
   Specifying deprecated flags `importsNotUsedAsValues` or `preserveValueImports` alongside `verbatimModuleSyntax` produces compiler options diagnostics `TS5102`, instructing the developer to use `verbatimModuleSyntax` instead.

7. **Single-File Transpilation Alignment**:
   Single-file transpilers (e.g., `ts.transpileModule`, bundler plugins) can safely emit ESM/CJS without inspecting AST symbol tables, dropping only nodes explicitly decorated with `type`.

## How the Wrong Expectation Fails
- A developer or coding assistant expecting `import { MyType }` to automatically elide during compilation will encounter build failures with `TS1484`.
- A developer expecting `export default` in CommonJS modules to transpile to `exports.default` will fail with `TS1287`.
- A developer expecting `tsc` to strip unused value imports will observe that `verbatimModuleSyntax` intentionally emits them verbatim into the target bundle.
csx.json
{"case":{"believed":"TypeScript automatically elides type-only named imports and unused value imports during ECMAScript emit regardless of whether type keywords or verbatimModuleSyntax are configured.","caseId":"case:sha256:ee7ff380a055aa1c7099fda80a036087074efcd234da09cb5d310037e9b96de7","contract":["When compilerOptions.verbatimModuleSyntax is enabled, importing a type without the type modifier fails type-checking with TS1484, and re-exporting a type without export type fails with TS1205, whereas type-only imports and inline type specifiers compile cleanly and are elided during emit.","compilerOptions.verbatimModuleSyntax preserves unused value imports verbatim in emitted JavaScript rather than eliding them","In CommonJS module format, compilerOptions.verbatimModuleSyntax rejects top-level export declarations with TS1287 and ES import declarations with TS1286, requiring import equals require and export equals syntax","In ECMAScript module format, compilerOptions.verbatimModuleSyntax rejects CommonJS export assignment syntax with TS1203","Specifying removed legacy options importsNotUsedAsValues or preserveValueImports alongside verbatimModuleSyntax produces configuration diagnostics with TS5102"],"goal":"Enforce type-only import/export syntax and module boundary semantics under compilerOptions.verbatimModuleSyntax in TypeScript 5.9.3","kind":"HOW","packages":["pkg:npm/typescript@5.9.3"],"schemaVersion":1,"symbols":["ts.CompilerOptions.verbatimModuleSyntax"]},"contractCommand":["node","test/contract.mjs"],"environment":{"arch":"x64","ecosystem":"npm","executionContext":"node","language":"node","os":"linux","packageManager":"npm","runtime":"node","schemaVersion":1},"license":"MIT-0","packages":["pkg:npm/typescript@5.9.3"],"schemaVersion":1,"symbols":["ts.CompilerOptions.verbatimModuleSyntax"],"verifierAdapter":"node-typescript@1"}
package-lock.json
{
  "name": "npm-typescript-wanted-5-9-3-ts-compileroptions-verbatimmodulesyntax",
  "version": "1.0.0",
  "lockfileVersion": 3,
  "requires": true,
  "packages": {
    "": {
      "name": "npm-typescript-wanted-5-9-3-ts-compileroptions-verbatimmodulesyntax",
      "version": "1.0.0",
      "dependencies": {
        "typescript": "5.9.3"
      }
    },
    "node_modules/typescript": {
      "version": "5.9.3",
      "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
      "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
      "license": "Apache-2.0",
      "bin": {
        "tsc": "bin/tsc",
        "tsserver": "bin/tsserver"
      },
      "engines": {
        "node": ">=14.17"
      }
    }
  }
}
package.json
{
  "name": "npm-typescript-wanted-5-9-3-ts-compileroptions-verbatimmodulesyntax",
  "version": "1.0.0",
  "type": "module",
  "scripts": {
    "test": "node test/contract.mjs"
  },
  "dependencies": {
    "typescript": "5.9.3"
  }
}
src/index.mjs
import ts from 'typescript';

const DEFAULT_LIB = `
declare var console: any;
interface Array<T> {}
interface Boolean {}
interface Function {}
interface IArguments {}
interface Number {}
interface Object {}
interface RegExp {}
interface String {}
`;

export function createVirtualHost(files, currentDir = '/project') {
  if (!('/lib.d.ts' in files)) {
    files['/lib.d.ts'] = DEFAULT_LIB;
  }

  return {
    getSourceFile: (fileName, languageVersion) => {
      const content = files[fileName];
      if (content !== undefined) {
        return ts.createSourceFile(
          fileName,
          content,
          languageVersion ?? ts.ScriptTarget.ES2022,
          true
        );
      }
      return undefined;
    },
    getDefaultLibFileName: () => '/lib.d.ts',
    writeFile: (fileName, content) => {
      files[fileName] = content;
    },
    getCurrentDirectory: () => currentDir,
    getDirectories: (dir) => {
      const prefix = dir.endsWith('/') ? dir : `${dir}/`;
      const dirs = new Set();
      for (const p of Object.keys(files)) {
        if (p.startsWith(prefix)) {
          const rest = p.slice(prefix.length);
          const slashIdx = rest.indexOf('/');
          if (slashIdx !== -1) dirs.add(rest.slice(0, slashIdx));
        }
      }
      return Array.from(dirs);
    },
    getCanonicalFileName: (f) => f,
    useCaseSensitiveFileNames: () => true,
    getNewLine: () => '\n',
    fileExists: (fileName) => fileName in files,
    readFile: (fileName) => files[fileName],
    directoryExists: (dir) => {
      const prefix = dir.endsWith('/') ? dir : `${dir}/`;
      return Object.keys(files).some((p) => p.startsWith(prefix));
    },
    realpath: (p) => p,
  };
}

export function compileVirtual(files, entryFiles, compilerOptions = {}) {
  const store = { ...files };
  const host = createVirtualHost(store);
  const program = ts.createProgram({
    rootNames: entryFiles,
    options: {
      target: ts.ScriptTarget.ES2022,
      skipLibCheck: true,
      ...compilerOptions,
    },
    host,
  });

  const optionsDiagnostics = program.getOptionsDiagnostics().map((d) => ({
    code: d.code,
    fileName: d.file ? d.file.fileName : undefined,
    message: ts.flattenDiagnosticMessageText(d.messageText, '\n'),
  }));

  const preDiagnostics = ts.getPreEmitDiagnostics(program).map((d) => ({
    code: d.code,
    fileName: d.file ? d.file.fileName : undefined,
    message: ts.flattenDiagnosticMessageText(d.messageText, '\n'),
  }));

  const emitResult = program.emit();
  const emitDiagnostics = emitResult.diagnostics.map((d) => ({
    code: d.code,
    fileName: d.file ? d.file.fileName : undefined,
    message: ts.flattenDiagnosticMessageText(d.messageText, '\n'),
  }));

  return {
    program,
    diagnostics: [...optionsDiagnostics, ...preDiagnostics, ...emitDiagnostics],
    optionsDiagnostics,
    preDiagnostics,
    emitDiagnostics,
    emitSkipped: emitResult.emitSkipped,
    host,
    emittedFiles: store,
  };
}

export function transpileSource(source, compilerOptions = {}) {
  return ts.transpileModule(source, {
    compilerOptions: {
      target: ts.ScriptTarget.ES2022,
      ...compilerOptions,
    },
  });
}

export { ts };
test/contract.mjs
import { strict as assert } from 'node:assert';
import { compileVirtual, transpileSource, ts } from '../src/index.mjs';

// --- Section 1: Type-only Named Imports under verbatimModuleSyntax ---

const typeImportFiles = {
  '/project/package.json': JSON.stringify({ name: 'test-project', type: 'module' }),
  '/project/src/types.ts': `
export type UserId = string;
export interface UserProfile { id: UserId; name: string; }
export const DEFAULT_USER: UserProfile = { id: 'usr-1', name: 'Anonymous' };
`,
  // Non-type import of type-only identifiers
  '/project/src/invalid-type-import.ts': `
import { UserId, UserProfile } from "./types.js";
const id: UserId = "usr-100";
const profile: UserProfile = { id, name: "Alice" };
console.log(id, profile);
`,
  // Valid type-only imports using 'import type' and inline 'type' modifier
  '/project/src/valid-type-import.ts': `
import type { UserId } from "./types.js";
import { type UserProfile, DEFAULT_USER } from "./types.js";
const id: UserId = DEFAULT_USER.id;
const profile: UserProfile = { id, name: DEFAULT_USER.name };
console.log(id, profile);
`,
};

// With verbatimModuleSyntax: false, importing a type without 'type' modifier succeeds cleanly
const noVmsTypeImport = compileVirtual(typeImportFiles, ['/project/src/invalid-type-import.ts'], {
  module: ts.ModuleKind.Node16,
  moduleResolution: ts.ModuleResolutionKind.Node16,
  verbatimModuleSyntax: false,
});
assert.strictEqual(
  noVmsTypeImport.diagnostics.length,
  0,
  'TypeScript without verbatimModuleSyntax allows importing types without type modifiers'
);

// With verbatimModuleSyntax: true, importing a type without 'type' modifier fails with TS1484
const vmsTypeImportInvalid = compileVirtual(typeImportFiles, ['/project/src/invalid-type-import.ts'], {
  module: ts.ModuleKind.Node16,
  moduleResolution: ts.ModuleResolutionKind.Node16,
  verbatimModuleSyntax: true,
});
assert.strictEqual(vmsTypeImportInvalid.diagnostics.length, 2);
assert.ok(vmsTypeImportInvalid.diagnostics.every((d) => d.code === 1484));
assert.ok(
  vmsTypeImportInvalid.diagnostics[0].message.includes('is a type and must be imported using a type-only import'),
  'TS1484 diagnostic directs the user to type-only imports'
);

// With verbatimModuleSyntax: true, using 'import type' and inline 'type' modifier compiles with 0 diagnostics
const vmsTypeImportValid = compileVirtual(typeImportFiles, ['/project/src/valid-type-import.ts'], {
  module: ts.ModuleKind.Node16,
  moduleResolution: ts.ModuleResolutionKind.Node16,
  verbatimModuleSyntax: true,
});
assert.strictEqual(
  vmsTypeImportValid.diagnostics.length,
  0,
  'verbatimModuleSyntax accepts type-only and inline-type imports cleanly'
);

// --- Section 2: Type Re-exports under verbatimModuleSyntax ---

const reexportFiles = {
  '/project/package.json': JSON.stringify({ name: 'test-project', type: 'module' }),
  '/project/src/models.ts': `
export type SessionToken = string;
export interface SessionData { token: SessionToken; expiresAt: number; }
`,
  // Invalid: re-exporting type without export type
  '/project/src/invalid-reexport.ts': `
import type { SessionToken } from "./models.js";
export { SessionToken };
`,
  // Invalid: re-exporting directly from module without type modifier
  '/project/src/invalid-direct-reexport.ts': `
export { SessionData } from "./models.js";
`,
  // Valid: using export type and inline type modifier
  '/project/src/valid-reexport.ts': `
export type { SessionToken } from "./models.js";
export { type SessionData } from "./models.js";
`,
};

// Re-export without type modifier fails under verbatimModuleSyntax with TS1205
const vmsReexportInvalid = compileVirtual(
  reexportFiles,
  ['/project/src/invalid-reexport.ts', '/project/src/invalid-direct-reexport.ts'],
  {
    module: ts.ModuleKind.Node16,
    moduleResolution: ts.ModuleResolutionKind.Node16,
    verbatimModuleSyntax: true,
  }
);
assert.strictEqual(vmsReexportInvalid.diagnostics.length, 2);
assert.ok(vmsReexportInvalid.diagnostics.every((d) => d.code === 1205));
assert.ok(
  vmsReexportInvalid.diagnostics[0].message.includes("requires using 'export type'"),
  'TS1205 diagnostic requires export type'
);

// Valid re-exports with export type compile cleanly
const vmsReexportValid = compileVirtual(reexportFiles, ['/project/src/valid-reexport.ts'], {
  module: ts.ModuleKind.Node16,
  moduleResolution: ts.ModuleResolutionKind.Node16,
  verbatimModuleSyntax: true,
});
assert.strictEqual(vmsReexportValid.diagnostics.length, 0, 'Re-exporting with export type passes compilation');

// --- Section 3: Verbatim Value Import Preservation vs Elision ---

const emitFiles = {
  '/project/package.json': JSON.stringify({ name: 'test-project', type: 'module' }),
  '/project/src/service.ts': `
export const usedService = () => 'active';
export const unusedService = () => 'dormant';
export type ServiceConfig = { retries: number };
`,
  '/project/src/consumer.ts': `
import { usedService, unusedService } from "./service.js";
import { type ServiceConfig } from "./service.js";
import type { ServiceConfig as ConfigAlias } from "./service.js";
import "./service.js";

const conf: ServiceConfig = { retries: 3 };
console.log(usedService());
`,
};

// Without verbatimModuleSyntax: unusedService is stripped from emit
const noVmsEmit = compileVirtual(emitFiles, ['/project/src/consumer.ts', '/project/src/service.ts'], {
  module: ts.ModuleKind.Node16,
  moduleResolution: ts.ModuleResolutionKind.Node16,
  verbatimModuleSyntax: false,
});
const noVmsJs = noVmsEmit.emittedFiles['/project/src/consumer.js'];
assert.ok(noVmsJs !== undefined, 'Consumer JavaScript file must be emitted');
assert.ok(noVmsJs.includes('usedService'), 'Used import must be present');
assert.ok(!noVmsJs.includes('unusedService'), 'Without verbatimModuleSyntax, unused value import is elided');

// With verbatimModuleSyntax: true: unusedService is PRESERVED verbatim
const vmsEmit = compileVirtual(emitFiles, ['/project/src/consumer.ts', '/project/src/service.ts'], {
  module: ts.ModuleKind.Node16,
  moduleResolution: ts.ModuleResolutionKind.Node16,
  verbatimModuleSyntax: true,
});
const vmsJs = vmsEmit.emittedFiles['/project/src/consumer.js'];
assert.ok(vmsJs !== undefined, 'Consumer JavaScript file must be emitted under verbatimModuleSyntax');
assert.ok(vmsJs.includes('unusedService'), 'verbatimModuleSyntax preserves unused value imports in emitted JS');
assert.ok(vmsJs.includes('usedService'), 'verbatimModuleSyntax preserves used value imports');
assert.ok(!vmsJs.includes('ServiceConfig'), 'verbatimModuleSyntax elides pure and inline type imports');
assert.ok(vmsJs.includes('import "./service.js";'), 'verbatimModuleSyntax preserves side-effect imports');

// --- Section 4: CommonJS Module Boundary Semantics ---

const cjsFiles = {
  '/project/package.json': JSON.stringify({ name: 'test-project', type: 'commonjs' }),
  '/project/src/cjs-dep.cts': `
const helper = () => 42;
export = helper;
`,
  // Invalid in CJS under verbatimModuleSyntax: export default
  '/project/src/cjs-export-default.cts': `
export default function run() { return 1; }
`,
  // Invalid in CJS under verbatimModuleSyntax: export const
  '/project/src/cjs-export-named.cts': `
export const apiVersion = "v1";
`,
  // Invalid in CJS under verbatimModuleSyntax: ES import
  '/project/src/cjs-es-import.cts': `
import helper from "./cjs-dep.cjs";
console.log(helper);
`,
  // Valid in CJS under verbatimModuleSyntax: import = require() and export =
  '/project/src/cjs-valid.cts': `
import helper = require("./cjs-dep.cjs");
const app = () => helper();
export = app;
`,
};

// CJS invalid constructs fail under verbatimModuleSyntax
const cjsDefaultRes = compileVirtual(cjsFiles, ['/project/src/cjs-export-default.cts'], {
  module: ts.ModuleKind.Node16,
  moduleResolution: ts.ModuleResolutionKind.Node16,
  verbatimModuleSyntax: true,
});
assert.strictEqual(cjsDefaultRes.diagnostics.length, 1);
assert.strictEqual(cjsDefaultRes.diagnostics[0].code, 1287, 'export default in CommonJS fails with TS1287');

const cjsNamedRes = compileVirtual(cjsFiles, ['/project/src/cjs-export-named.cts'], {
  module: ts.ModuleKind.Node16,
  moduleResolution: ts.ModuleResolutionKind.Node16,
  verbatimModuleSyntax: true,
});
assert.strictEqual(cjsNamedRes.diagnostics.length, 1);
assert.strictEqual(cjsNamedRes.diagnostics[0].code, 1287, 'named export in CommonJS fails with TS1287');

const cjsImportRes = compileVirtual(cjsFiles, ['/project/src/cjs-es-import.cts'], {
  module: ts.ModuleKind.Node16,
  moduleResolution: ts.ModuleResolutionKind.Node16,
  verbatimModuleSyntax: true,
});
assert.strictEqual(cjsImportRes.diagnostics.length, 1);
assert.strictEqual(cjsImportRes.diagnostics[0].code, 1286, 'ES import in CommonJS fails with TS1286');

// CJS valid constructs compile with 0 diagnostics
const cjsValid = compileVirtual(cjsFiles, ['/project/src/cjs-valid.cts', '/project/src/cjs-dep.cts'], {
  module: ts.ModuleKind.Node16,
  moduleResolution: ts.ModuleResolutionKind.Node16,
  verbatimModuleSyntax: true,
});
assert.strictEqual(cjsValid.diagnostics.length, 0, 'import = require and export = compile cleanly in CJS');

// --- Section 5: ECMAScript Module Boundary Semantics ---

const esmFiles = {
  '/project/package.json': JSON.stringify({ name: 'test-project', type: 'module' }),
  // Invalid in ESM: export = assignment
  '/project/src/esm-export-assign.mts': `
const server = { port: 8080 };
export = server;
`,
  // Valid in ESM: export default and export const
  '/project/src/esm-valid-exports.mts': `
export const serverPort = 8080;
export default function startServer() { return serverPort; }
`,
};

const esmInvalid = compileVirtual(esmFiles, ['/project/src/esm-export-assign.mts'], {
  module: ts.ModuleKind.Node16,
  moduleResolution: ts.ModuleResolutionKind.Node16,
  verbatimModuleSyntax: true,
});
assert.strictEqual(esmInvalid.diagnostics.length, 1);
assert.strictEqual(esmInvalid.diagnostics[0].code, 1203, 'export = fails in ESM under verbatimModuleSyntax with TS1203');

const esmValid = compileVirtual(esmFiles, ['/project/src/esm-valid-exports.mts'], {
  module: ts.ModuleKind.Node16,
  moduleResolution: ts.ModuleResolutionKind.Node16,
  verbatimModuleSyntax: true,
});
assert.strictEqual(esmValid.diagnostics.length, 0, 'ESM export default and named export compile cleanly');

// --- Section 6: Mutual Exclusivity and Legacy Options Diagnostics ---

const dummyFiles = {
  '/project/src/main.ts': 'export const answer = 42;',
};

// Specifying deprecated importsNotUsedAsValues alongside verbatimModuleSyntax produces TS5102
const inuavConflict = compileVirtual(dummyFiles, ['/project/src/main.ts'], {
  verbatimModuleSyntax: true,
  importsNotUsedAsValues: ts.ImportsNotUsedAsValues.Error,
});
assert.ok(inuavConflict.optionsDiagnostics.some((d) => d.code === 5102));

// Specifying deprecated preserveValueImports alongside verbatimModuleSyntax produces TS5102
const pviConflict = compileVirtual(dummyFiles, ['/project/src/main.ts'], {
  verbatimModuleSyntax: true,
  preserveValueImports: true,
});
assert.ok(pviConflict.optionsDiagnostics.some((d) => d.code === 5102));

// --- Section 7: Single-File Transpilation Behavior ---

const sourceCode = `
import { ValueA, ValueB } from "./values.js";
import { type TypeOnly, ValueC } from "./mixed.js";
import type { StandaloneType } from "./types.js";
import "./side-effects.js";

export { ValueA };
export { type TypeOnly };
export type { StandaloneType };
export { ValueB, ValueC };
`;

const transpileRes = transpileSource(sourceCode, {
  module: ts.ModuleKind.ESNext,
  verbatimModuleSyntax: true,
});

assert.ok(transpileRes.outputText.includes('import { ValueA, ValueB } from "./values.js";'));
assert.ok(transpileRes.outputText.includes('import { ValueC } from "./mixed.js";'));
assert.ok(!transpileRes.outputText.includes('TypeOnly'));
assert.ok(!transpileRes.outputText.includes('StandaloneType'));
assert.ok(transpileRes.outputText.includes('import "./side-effects.js";'));
assert.ok(transpileRes.outputText.includes('export { ValueA };'));
assert.ok(transpileRes.outputText.includes('export {};'));
assert.ok(transpileRes.outputText.includes('export { ValueB, ValueC };'));

console.log('CONTRACT PASS: ts.CompilerOptions.verbatimModuleSyntax verified in TypeScript 5.9.3');

Seeder de origen

csx-seed