`ts-check` used with `@typedef` causes an error on `module.exports = ...`
Steps to reproduce
// @ts-check
/** @typedef {number} Foo */
module.exports = {};
Behavior with [email protected]
No reported errors:
https://www.typescriptlang.org/play/?ts=5.9.2#code/PTAEAEBcGcFoGMAWBTeBrAUB4AqHFIBPAB2QBNkAzUAbwDsBXAWwCNkAnAX1ADEB7PqBzAsTPmQYAbZADpkAD2J92MUAF5anANwYgA
Behavior with tsgo
index.cjs:5:1 - error TS2309: An export assignment cannot be used in a module with other exported elements.
5 module.exports = {};
~~~~~~~~~~~~~~~~~~~
Found 1 error in index.cjs:5
This doesn't appear unless ts-check is set, even if allowJs is set to true.
#1688 would have fixed this but was closed
Here is a test case that shows a variant of this problem:
// @module: nodenext
// @target: esnext
// @outDir: ./out
// @allowJs: true
// @checkJs: true
// @noUnusedLocals: true
// @noUnusedParameters: true
// @declaration: true
// @filename: test.js
const t = require("./types");
/** @type {t.MyType} */
const obj = { a: 42, b: "hello" };
console.log(obj);
// @filename: types.js
/** @typedef {{ a: number, b: string }} MyType */
module.exports = {};
Nets:
test.js(1,7): error TS6133: 't' is declared but its value is never read.
test.js(3,12): error TS2503: Cannot find namespace 't'.
types.js(3,1): error TS2309: An export assignment cannot be used in a module with other exported elements.
==== test.js (2 errors) ====
const t = require("./types");
~
!!! error TS6133: 't' is declared but its value is never read.
/** @type {t.MyType} */
~
!!! error TS2503: Cannot find namespace 't'.
const obj = { a: 42, b: "hello" };
console.log(obj);
==== types.js (1 errors) ====
/** @typedef {{ a: number, b: string }} MyType */
module.exports = {};
~~~~~~~~~~~~~~~~~~~
!!! error TS2309: An export assignment cannot be used in a module with other exported elements.
Along with:
//// [types.d.ts]
/** @typedef {{ a: number, b: string }} MyType */
export type MyType = {
a: number;
b: string;
};
declare const _default: {};
export = _default;
If you remove module.exports, we still add the export modifier (another different bug), but the emit is correctish
//// [types.d.ts]
export type MyType = {
a: number;
b: string;
};
/** @typedef {{ a: number, b: string }} MyType */
A workaround for type-only files like this is to not use module.exports = {}, but instead write something like module.exports.nothing = undefined which instead generates separate declarations rather than an export = node.