From 5c11cc7fcccbc2ed0576bafb0a17a7ccd5570792 Mon Sep 17 00:00:00 2001 From: Simon Holthausen Date: Tue, 2 Jul 2024 15:09:21 +0200 Subject: [PATCH] fix: better way of preventing unintended exports https://github.com/sveltejs/svelte/issues/12202 revealed that TypeScript has a harder time tracing imports when they are indirectly exposed, e.g. `function foo(): void; ... export { foo }` instead of `export function foo(): void;`, which can lead to bugs down the line. Ultimately this is a TypeScript limitation but in the meantime adding a lone `export {}` along `export function/const/etc` statements has the same effect as #82 --- CHANGELOG.md | 4 ++++ src/create-module-declaration.js | 18 ++++++++---------- test/samples/ambient-imports/output/index.d.ts | 2 ++ test/samples/basic/output 5.5/index.d.ts | 12 ++++++------ test/samples/basic/output 5.5/index.d.ts.map | 4 ++-- test/samples/const-namespace/output/index.d.ts | 4 +++- test/samples/declare-module/output/index.d.ts | 2 ++ .../deconflict-priority/output/index.d.ts | 2 ++ test/samples/enum/output/index.d.ts | 4 +++- .../export-default-as/output/index.d.ts | 2 ++ .../export-default-function/output/index.d.ts | 2 ++ .../export-default-value/output/index.d.ts | 2 ++ test/samples/export-from/output/index.d.ts | 2 ++ test/samples/export-named-as/output/index.d.ts | 2 ++ test/samples/export-type/output/index.d.ts | 4 +++- test/samples/generics/output/index.d.ts | 2 ++ .../output/index.d.ts | 4 +++- .../import-external-default/output/index.d.ts | 4 +++- .../output/index.d.ts | 3 ++- .../import-external-named-as/output/index.d.ts | 3 ++- .../import-external-named/output/index.d.ts | 3 ++- .../samples/jsdoc-import/output 5.5/index.d.ts | 6 +++--- .../jsdoc-import/output 5.5/index.d.ts.map | 4 ++-- .../namespace-exports/output/index.d.ts | 4 +++- test/samples/overloads/output/index.d.ts | 4 +++- test/samples/path-config/output/index.d.ts | 2 ++ .../preserve-comments/output/index.d.ts | 2 ++ .../preserved-jsdoc-tags/output/index.d.ts | 2 ++ test/samples/throws/output/index.d.ts | 2 ++ .../output/index.d.ts | 2 ++ test/samples/ts/output/index.d.ts | 4 ++++ test/samples/ts/output/index.d.ts.map | 2 +- 32 files changed, 85 insertions(+), 34 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a197c22..098a34a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # dts-buddy changelog +## 0.5.1 + +- Use more TypeScript-friendly way of preventing unintended exports ([#85](https://github.com/Rich-Harris/dts-buddy/pull/85)) + ## 0.5.0 - Prevent unintended exports ([#82](https://github.com/Rich-Harris/dts-buddy/pull/82)) diff --git a/src/create-module-declaration.js b/src/create-module-declaration.js index 8b23514..c0e8144 100644 --- a/src/create-module-declaration.js +++ b/src/create-module-declaration.js @@ -398,24 +398,22 @@ export function create_module_declaration(id, entry, created, resolve) { if (mod) content += '\n' + mod; } - if (export_specifiers.length > 0) { - content += `\n\n\texport { ${export_specifiers.join(', ')} };`; - } - // finally, export any bindings that are exported from external modules - /** @type {string[]} */ - const specifiers = []; - for (const name of exports) { const declaration = trace_export(entry, name); if (declaration?.external) { - specifiers.push(declaration.alias); + export_specifiers.push(declaration.alias); } } - if (specifiers.length > 0) { - content += `\n\texport { ${specifiers.join(', ')} };`; + // Always add an export { .. } statement, even if there are no exports. This ensures + // that only the public types are exposed to consumers of the declaration file. Due to some + // old TypeScript inconsistency, omitting the export statement would expose all types. + if (export_specifiers.length > 0) { + content += `\n\n\texport { ${export_specifiers.join(', ')} };`; + } else { + content += '\n\n\texport {};'; } content += `\n}`; diff --git a/test/samples/ambient-imports/output/index.d.ts b/test/samples/ambient-imports/output/index.d.ts index 358f4f0..2db6981 100644 --- a/test/samples/ambient-imports/output/index.d.ts +++ b/test/samples/ambient-imports/output/index.d.ts @@ -2,6 +2,8 @@ declare module 'ambient-imports' { export interface Foo {} + + export {}; } //# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/test/samples/basic/output 5.5/index.d.ts b/test/samples/basic/output 5.5/index.d.ts index 68a43e3..741d233 100644 --- a/test/samples/basic/output 5.5/index.d.ts +++ b/test/samples/basic/output 5.5/index.d.ts @@ -1,6 +1,6 @@ declare module 'basic' { /** A vector with two components */ - interface Vector2 { + export interface Vector2 { /** The x component */ x: number; /** The y component */ @@ -11,18 +11,18 @@ declare module 'basic' { * @param a the first vector * @param b the second vector * */ - function add(a: Vector2, b: Vector2): Vector2; + export function add(a: Vector2, b: Vector2): Vector2; - export { Vector2, add }; + export {}; } declare module 'basic/subpackage' { /** * Multiply two vectors * */ - function multiply(a: import("basic").Vector2, b: import("basic").Vector2): import("basic").Vector2; + export function multiply(a: import("basic").Vector2, b: import("basic").Vector2): import("basic").Vector2; - export { multiply }; + export {}; } -//# sourceMappingURL=index.d.ts.map +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/test/samples/basic/output 5.5/index.d.ts.map b/test/samples/basic/output 5.5/index.d.ts.map index 3e724d7..6688801 100644 --- a/test/samples/basic/output 5.5/index.d.ts.map +++ b/test/samples/basic/output 5.5/index.d.ts.map @@ -16,5 +16,5 @@ null, null ], - "mappings": ";;WACiBA,OAAOA;;;;;;;;;;;UCKRC,GAAGA;;;;;;;;;UCAHC,QAAQA" -} + "mappings": ";;kBACiBA,OAAOA;;;;;;;;;;;iBCKRC,GAAGA;;;;;;;;;iBCAHC,QAAQA" +} \ No newline at end of file diff --git a/test/samples/const-namespace/output/index.d.ts b/test/samples/const-namespace/output/index.d.ts index ed28fa8..385986d 100644 --- a/test/samples/const-namespace/output/index.d.ts +++ b/test/samples/const-namespace/output/index.d.ts @@ -2,6 +2,8 @@ declare module 'const-namespace' { export namespace a { let x: number; } + + export {}; } -//# sourceMappingURL=index.d.ts.map +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/test/samples/declare-module/output/index.d.ts b/test/samples/declare-module/output/index.d.ts index 97c7f66..990fe28 100644 --- a/test/samples/declare-module/output/index.d.ts +++ b/test/samples/declare-module/output/index.d.ts @@ -1,5 +1,7 @@ declare module 'declare-module' { export interface Foo {} + + export {}; } //# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/test/samples/deconflict-priority/output/index.d.ts b/test/samples/deconflict-priority/output/index.d.ts index fc5f215..e631e80 100644 --- a/test/samples/deconflict-priority/output/index.d.ts +++ b/test/samples/deconflict-priority/output/index.d.ts @@ -2,6 +2,8 @@ declare module 'deconflict-priority' { export function x(foo: Foo, bar: Bar): void; interface Foo {} interface Bar {} + + export {}; } //# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/test/samples/enum/output/index.d.ts b/test/samples/enum/output/index.d.ts index de458d9..1e199cc 100644 --- a/test/samples/enum/output/index.d.ts +++ b/test/samples/enum/output/index.d.ts @@ -4,6 +4,8 @@ declare module 'enum' { VEGETABLE = 1, MINERAL = 2 } + + export {}; } -//# sourceMappingURL=index.d.ts.map +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/test/samples/export-default-as/output/index.d.ts b/test/samples/export-default-as/output/index.d.ts index 4beb443..dae8af7 100644 --- a/test/samples/export-default-as/output/index.d.ts +++ b/test/samples/export-default-as/output/index.d.ts @@ -3,6 +3,8 @@ declare module 'export-default-as' { * Add two numbers * */ export function add(a: number, b: number): number; + + export {}; } //# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/test/samples/export-default-function/output/index.d.ts b/test/samples/export-default-function/output/index.d.ts index dc78626..bd83584 100644 --- a/test/samples/export-default-function/output/index.d.ts +++ b/test/samples/export-default-function/output/index.d.ts @@ -1,5 +1,7 @@ declare module 'export-default-function' { export default function foo(): void; + + export {}; } //# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/test/samples/export-default-value/output/index.d.ts b/test/samples/export-default-value/output/index.d.ts index 5ef499e..ea47de0 100644 --- a/test/samples/export-default-value/output/index.d.ts +++ b/test/samples/export-default-value/output/index.d.ts @@ -1,6 +1,8 @@ declare module 'export-default-value' { const _default: 42; export default _default; + + export {}; } //# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/test/samples/export-from/output/index.d.ts b/test/samples/export-from/output/index.d.ts index 05f2123..03aca78 100644 --- a/test/samples/export-from/output/index.d.ts +++ b/test/samples/export-from/output/index.d.ts @@ -1,5 +1,7 @@ declare module 'export-from' { export const foo: "hello"; + + export {}; } //# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/test/samples/export-named-as/output/index.d.ts b/test/samples/export-named-as/output/index.d.ts index 808a3b2..2de976f 100644 --- a/test/samples/export-named-as/output/index.d.ts +++ b/test/samples/export-named-as/output/index.d.ts @@ -3,6 +3,8 @@ declare module 'export-named-as' { * Add two numbers * */ export function plus(a: number, b: number): number; + + export {}; } //# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/test/samples/export-type/output/index.d.ts b/test/samples/export-type/output/index.d.ts index da8fc45..87b8ce4 100644 --- a/test/samples/export-type/output/index.d.ts +++ b/test/samples/export-type/output/index.d.ts @@ -1,6 +1,8 @@ declare module 'export-type' { export type D = {}; export class B {} + + export {}; } -//# sourceMappingURL=index.d.ts.map +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/test/samples/generics/output/index.d.ts b/test/samples/generics/output/index.d.ts index 5912672..fafa0aa 100644 --- a/test/samples/generics/output/index.d.ts +++ b/test/samples/generics/output/index.d.ts @@ -2,6 +2,8 @@ declare module 'generics' { export interface Foo { bar: T; } + + export {}; } //# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/test/samples/ignores-missing-sourcemap-segments/output/index.d.ts b/test/samples/ignores-missing-sourcemap-segments/output/index.d.ts index ba6510f..28811c5 100644 --- a/test/samples/ignores-missing-sourcemap-segments/output/index.d.ts +++ b/test/samples/ignores-missing-sourcemap-segments/output/index.d.ts @@ -3,6 +3,8 @@ declare module 'ignores-missing-sourcemap-segments' { export namespace object { let answer: number; } + + export {}; } -//# sourceMappingURL=index.d.ts.map +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/test/samples/import-external-default/output/index.d.ts b/test/samples/import-external-default/output/index.d.ts index 784438d..403895b 100644 --- a/test/samples/import-external-default/output/index.d.ts +++ b/test/samples/import-external-default/output/index.d.ts @@ -1,6 +1,8 @@ declare module 'import-external-default' { import type { default as x } from 'external'; export function foo(input: x): x; + + export {}; } -//# sourceMappingURL=index.d.ts.map +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/test/samples/import-external-named-as-conflict/output/index.d.ts b/test/samples/import-external-named-as-conflict/output/index.d.ts index 316f087..5a1af1f 100644 --- a/test/samples/import-external-named-as-conflict/output/index.d.ts +++ b/test/samples/import-external-named-as-conflict/output/index.d.ts @@ -1,7 +1,8 @@ declare module 'import-external-named-as-conflict' { import type { foo as f } from 'external'; export function foo(): void; + export { f }; } -//# sourceMappingURL=index.d.ts.map +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/test/samples/import-external-named-as/output/index.d.ts b/test/samples/import-external-named-as/output/index.d.ts index ce7b2fb..36cfe5a 100644 --- a/test/samples/import-external-named-as/output/index.d.ts +++ b/test/samples/import-external-named-as/output/index.d.ts @@ -1,6 +1,7 @@ declare module 'import-external-named-as' { import type { foo as f } from 'external'; + export { f }; } -//# sourceMappingURL=index.d.ts.map +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/test/samples/import-external-named/output/index.d.ts b/test/samples/import-external-named/output/index.d.ts index 2c9a23f..628656c 100644 --- a/test/samples/import-external-named/output/index.d.ts +++ b/test/samples/import-external-named/output/index.d.ts @@ -1,6 +1,7 @@ declare module 'import-external-named' { import type { foo } from 'external'; + export { foo }; } -//# sourceMappingURL=index.d.ts.map +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/test/samples/jsdoc-import/output 5.5/index.d.ts b/test/samples/jsdoc-import/output 5.5/index.d.ts index 0894aee..5cfc526 100644 --- a/test/samples/jsdoc-import/output 5.5/index.d.ts +++ b/test/samples/jsdoc-import/output 5.5/index.d.ts @@ -4,7 +4,7 @@ declare module 'jsdoc-import' { * @param a the first vector * @param b the second vector * */ - function add(a: Vector2, b: Vector2): Vector2; + export function add(a: Vector2, b: Vector2): Vector2; /** A vector with two components */ interface Vector2 { /** The x component */ @@ -13,7 +13,7 @@ declare module 'jsdoc-import' { y: number; } - export { add }; + export {}; } -//# sourceMappingURL=index.d.ts.map +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/test/samples/jsdoc-import/output 5.5/index.d.ts.map b/test/samples/jsdoc-import/output 5.5/index.d.ts.map index f12e450..6cbc914 100644 --- a/test/samples/jsdoc-import/output 5.5/index.d.ts.map +++ b/test/samples/jsdoc-import/output 5.5/index.d.ts.map @@ -13,5 +13,5 @@ null, null ], - "mappings": ";;;;;;UAQgBA,GAAGA;;WCPFC,OAAOA" -} + "mappings": ";;;;;;iBAQgBA,GAAGA;;WCPFC,OAAOA" +} \ No newline at end of file diff --git a/test/samples/namespace-exports/output/index.d.ts b/test/samples/namespace-exports/output/index.d.ts index a64874c..f37960c 100644 --- a/test/samples/namespace-exports/output/index.d.ts +++ b/test/samples/namespace-exports/output/index.d.ts @@ -8,6 +8,8 @@ declare module 'namespace-exports' { y: string; } } + + export {}; } -//# sourceMappingURL=index.d.ts.map +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/test/samples/overloads/output/index.d.ts b/test/samples/overloads/output/index.d.ts index d6cf3c6..c229221 100644 --- a/test/samples/overloads/output/index.d.ts +++ b/test/samples/overloads/output/index.d.ts @@ -5,6 +5,8 @@ declare module 'overloads' { } export function baz(input: Foo): Foo; export function baz(input: Bar): Bar; + + export {}; } -//# sourceMappingURL=index.d.ts.map +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/test/samples/path-config/output/index.d.ts b/test/samples/path-config/output/index.d.ts index aa38551..e8d91d7 100644 --- a/test/samples/path-config/output/index.d.ts +++ b/test/samples/path-config/output/index.d.ts @@ -12,6 +12,8 @@ declare module 'path-config' { type Input = number; type Output = number; export function foo_nested(input: Input): Output; + + export {}; } //# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/test/samples/preserve-comments/output/index.d.ts b/test/samples/preserve-comments/output/index.d.ts index c71bb69..f8acd82 100644 --- a/test/samples/preserve-comments/output/index.d.ts +++ b/test/samples/preserve-comments/output/index.d.ts @@ -3,6 +3,8 @@ declare module 'preserve-comments' { * @deprecated */ export function a(): number; + + export {}; } //# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/test/samples/preserved-jsdoc-tags/output/index.d.ts b/test/samples/preserved-jsdoc-tags/output/index.d.ts index 6a8a452..59ff832 100644 --- a/test/samples/preserved-jsdoc-tags/output/index.d.ts +++ b/test/samples/preserved-jsdoc-tags/output/index.d.ts @@ -6,6 +6,8 @@ declare module 'preserved-jsdoc-tags' { * const three = add(1, 2); * */ export function add(a: number, b: number): number; + + export {}; } //# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/test/samples/throws/output/index.d.ts b/test/samples/throws/output/index.d.ts index 77c3843..7167cdd 100644 --- a/test/samples/throws/output/index.d.ts +++ b/test/samples/throws/output/index.d.ts @@ -3,6 +3,8 @@ declare module 'throws' { * @throws {Error} nope * */ export function nope(): never; + + export {}; } //# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/test/samples/treeshaking-inline-import/output/index.d.ts b/test/samples/treeshaking-inline-import/output/index.d.ts index 5d9875f..bc32e46 100644 --- a/test/samples/treeshaking-inline-import/output/index.d.ts +++ b/test/samples/treeshaking-inline-import/output/index.d.ts @@ -10,6 +10,8 @@ declare module 'treeshaking-inline-import' { /** The y component */ y: number; } + + export {}; } //# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/test/samples/ts/output/index.d.ts b/test/samples/ts/output/index.d.ts index 8615bd9..030af65 100644 --- a/test/samples/ts/output/index.d.ts +++ b/test/samples/ts/output/index.d.ts @@ -15,6 +15,8 @@ declare module 'ts' { * Add two vectors */ export function add(a: Vector2, b: Vector2): Vector2; + + export {}; } declare module 'ts/subpackage' { @@ -23,6 +25,8 @@ declare module 'ts/subpackage' { * Multiply two vectors */ export function multiply(a: Vector2, b: Vector2): Vector2; + + export {}; } //# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/test/samples/ts/output/index.d.ts.map b/test/samples/ts/output/index.d.ts.map index 2bf5834..400bc4a 100644 --- a/test/samples/ts/output/index.d.ts.map +++ b/test/samples/ts/output/index.d.ts.map @@ -15,5 +15,5 @@ null, null ], - "mappings": ";;kBACiBA,OAAOA;;;;;;;kBAQPC,OAAOA;;;;;;;iBAQRC,GAAGA;;;;;;;;iBCZHC,QAAQA" + "mappings": ";;kBACiBA,OAAOA;;;;;;;kBAQPC,OAAOA;;;;;;;iBAQRC,GAAGA;;;;;;;;;;iBCZHC,QAAQA" } \ No newline at end of file