mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-05 16:38:05 -06:00
Fix export * that resolves to something type-only (#36558)
* Fix `export *` that resolves to something type-only * Add same tests but non-tsserver
This commit is contained in:
parent
8db1d7bc6d
commit
86556d6c03
@ -2372,7 +2372,10 @@ namespace ts {
|
||||
|
||||
function getTargetOfNamespaceExport(node: NamespaceExport, dontResolveAlias: boolean): Symbol | undefined {
|
||||
const moduleSpecifier = node.parent.moduleSpecifier;
|
||||
return moduleSpecifier && resolveESModuleSymbol(resolveExternalModuleName(node, moduleSpecifier), moduleSpecifier, dontResolveAlias, /*suppressUsageError*/ false);
|
||||
const immediate = moduleSpecifier && resolveExternalModuleName(node, moduleSpecifier);
|
||||
const resolved = moduleSpecifier && resolveESModuleSymbol(immediate, moduleSpecifier, dontResolveAlias, /*suppressUsageError*/ false);
|
||||
markSymbolOfAliasDeclarationIfTypeOnly(node, immediate, resolved, /*overwriteEmpty*/ false);
|
||||
return resolved;
|
||||
}
|
||||
|
||||
// This function creates a synthetic symbol that combines the value side of one symbol with the
|
||||
@ -2521,7 +2524,9 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getTargetOfNamespaceExportDeclaration(node: NamespaceExportDeclaration, dontResolveAlias: boolean): Symbol {
|
||||
return resolveExternalModuleSymbol(node.parent.symbol, dontResolveAlias);
|
||||
const resolved = resolveExternalModuleSymbol(node.parent.symbol, dontResolveAlias);
|
||||
markSymbolOfAliasDeclarationIfTypeOnly(node, /*immediateTarget*/ undefined, resolved, /*overwriteEmpty*/ false);
|
||||
return resolved;
|
||||
}
|
||||
|
||||
function getTargetOfExportSpecifier(node: ExportSpecifier, meaning: SymbolFlags, dontResolveAlias?: boolean) {
|
||||
|
||||
@ -14,7 +14,7 @@ namespace ts.projectSystem {
|
||||
content: "import { a } from './b'; new a.A();"
|
||||
};
|
||||
|
||||
assertUsageError([a, b, c], c);
|
||||
assertUsageError([a, b, c], c, Diagnostics._0_cannot_be_used_as_a_value_because_it_was_imported_using_import_type);
|
||||
});
|
||||
|
||||
it("named export -> type-only named import -> named export -> named import", () => {
|
||||
@ -31,7 +31,7 @@ namespace ts.projectSystem {
|
||||
content: "import { A } from './b'; new A();"
|
||||
};
|
||||
|
||||
assertUsageError([a, b, c], c);
|
||||
assertUsageError([a, b, c], c, Diagnostics._0_cannot_be_used_as_a_value_because_it_was_imported_using_import_type);
|
||||
});
|
||||
|
||||
it("named export -> type-only namespace import -> export equals -> import equals", () => {
|
||||
@ -48,7 +48,7 @@ namespace ts.projectSystem {
|
||||
content: "import a = require('./b'); new a.A();"
|
||||
};
|
||||
|
||||
assertUsageError([a, b, c], c);
|
||||
assertUsageError([a, b, c], c, Diagnostics._0_cannot_be_used_as_a_value_because_it_was_imported_using_import_type);
|
||||
});
|
||||
|
||||
it("named export -> type-only namespace import -> export default -> import default", () => {
|
||||
@ -65,13 +65,13 @@ namespace ts.projectSystem {
|
||||
content: "import a from './b'; new a.A();"
|
||||
};
|
||||
|
||||
assertUsageError([a, b, c], c);
|
||||
assertUsageError([a, b, c], c, Diagnostics._0_cannot_be_used_as_a_value_because_it_was_imported_using_import_type);
|
||||
});
|
||||
|
||||
it("export default -> type-only import default -> export default -> import default", () => {
|
||||
const a = {
|
||||
path: "/a.ts",
|
||||
content: "export defai;t class A {}"
|
||||
content: "export default class A {}"
|
||||
};
|
||||
const b = {
|
||||
path: "/b.ts",
|
||||
@ -82,11 +82,74 @@ namespace ts.projectSystem {
|
||||
content: "import A from './b'; new A();"
|
||||
};
|
||||
|
||||
assertUsageError([a, b, c], c);
|
||||
assertUsageError([a, b, c], c, Diagnostics._0_cannot_be_used_as_a_value_because_it_was_imported_using_import_type);
|
||||
});
|
||||
|
||||
it("named export -> type-only export from -> export star from -> named import", () => {
|
||||
const a = {
|
||||
path: "/a.ts",
|
||||
content: "export class A {}"
|
||||
};
|
||||
const b = {
|
||||
path: "/b.ts",
|
||||
content: "export type { A } from './a';"
|
||||
};
|
||||
const c = {
|
||||
path: "/c.ts",
|
||||
content: "export * from './b';"
|
||||
};
|
||||
const d = {
|
||||
path: "/d.ts",
|
||||
content: "import { A } from './c'; new A();"
|
||||
};
|
||||
|
||||
assertUsageError([a, b, c, d], d, Diagnostics._0_cannot_be_used_as_a_value_because_it_was_exported_using_export_type);
|
||||
});
|
||||
|
||||
it("named export -> export namespace from -> type-only named import -> named export -> named import", () => {
|
||||
const a = {
|
||||
path: "/a.ts",
|
||||
content: "export class A {}"
|
||||
};
|
||||
const b = {
|
||||
path: "/b.ts",
|
||||
content: "export * as a from './a';"
|
||||
};
|
||||
const c = {
|
||||
path: "/c.ts",
|
||||
content: "import type { a } from './b'; export { a };"
|
||||
};
|
||||
const d = {
|
||||
path: "/d.ts",
|
||||
content: "import { a } from './c'; new a.A();"
|
||||
};
|
||||
|
||||
assertUsageError([a, b, c, d], d, Diagnostics._0_cannot_be_used_as_a_value_because_it_was_imported_using_import_type);
|
||||
});
|
||||
|
||||
it("named export -> type-only export from -> export namespace from -> named import", () => {
|
||||
const a = {
|
||||
path: "/a.ts",
|
||||
content: "export class A {}"
|
||||
};
|
||||
const b = {
|
||||
path: "/b.ts",
|
||||
content: "export type { A } from './a';"
|
||||
};
|
||||
const c = {
|
||||
path: "/c.ts",
|
||||
content: "export * as a from './b';"
|
||||
};
|
||||
const d = {
|
||||
path: "/d.ts",
|
||||
content: "import { a } from './c'; new a.A();"
|
||||
};
|
||||
|
||||
assertUsageError([a, b, c, d], d, Diagnostics.Property_0_does_not_exist_on_type_1);
|
||||
});
|
||||
});
|
||||
|
||||
function assertUsageError(files: readonly TestFSWithWatch.File[], openFile: TestFSWithWatch.File) {
|
||||
function assertUsageError(files: readonly TestFSWithWatch.File[], openFile: TestFSWithWatch.File, diagnostic: DiagnosticMessage) {
|
||||
const host = createServerHost(files);
|
||||
const session = createSession(host);
|
||||
openFilesForSession([openFile], session);
|
||||
@ -96,9 +159,6 @@ namespace ts.projectSystem {
|
||||
);
|
||||
const diagnostics = session.executeCommand(req).response as protocol.Diagnostic[];
|
||||
assert.lengthOf(diagnostics, 1);
|
||||
assert.oneOf(diagnostics[0].code, [
|
||||
Diagnostics._0_cannot_be_used_as_a_value_because_it_was_imported_using_import_type.code,
|
||||
Diagnostics._0_cannot_be_used_as_a_value_because_it_was_exported_using_export_type.code
|
||||
]);
|
||||
assert.equal(diagnostics[0].code, diagnostic.code);
|
||||
}
|
||||
}
|
||||
|
||||
19
tests/baselines/reference/exportNamespace1.errors.txt
Normal file
19
tests/baselines/reference/exportNamespace1.errors.txt
Normal file
@ -0,0 +1,19 @@
|
||||
tests/cases/conformance/externalModules/typeOnly/d.ts(2,5): error TS1362: 'A' cannot be used as a value because it was exported using 'export type'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/externalModules/typeOnly/a.ts (0 errors) ====
|
||||
export class A {}
|
||||
|
||||
==== tests/cases/conformance/externalModules/typeOnly/b.ts (0 errors) ====
|
||||
export type { A } from './a';
|
||||
|
||||
==== tests/cases/conformance/externalModules/typeOnly/c.ts (0 errors) ====
|
||||
export * from './b';
|
||||
|
||||
==== tests/cases/conformance/externalModules/typeOnly/d.ts (1 errors) ====
|
||||
import { A } from './c';
|
||||
new A(); // Error
|
||||
~
|
||||
!!! error TS1362: 'A' cannot be used as a value because it was exported using 'export type'.
|
||||
!!! related TS1377 tests/cases/conformance/externalModules/typeOnly/b.ts:1:15: 'A' was exported here.
|
||||
|
||||
39
tests/baselines/reference/exportNamespace1.js
Normal file
39
tests/baselines/reference/exportNamespace1.js
Normal file
@ -0,0 +1,39 @@
|
||||
//// [tests/cases/conformance/externalModules/typeOnly/exportNamespace1.ts] ////
|
||||
|
||||
//// [a.ts]
|
||||
export class A {}
|
||||
|
||||
//// [b.ts]
|
||||
export type { A } from './a';
|
||||
|
||||
//// [c.ts]
|
||||
export * from './b';
|
||||
|
||||
//// [d.ts]
|
||||
import { A } from './c';
|
||||
new A(); // Error
|
||||
|
||||
|
||||
//// [a.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
var A = /** @class */ (function () {
|
||||
function A() {
|
||||
}
|
||||
return A;
|
||||
}());
|
||||
exports.A = A;
|
||||
//// [b.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
//// [c.js]
|
||||
"use strict";
|
||||
function __export(m) {
|
||||
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
|
||||
}
|
||||
exports.__esModule = true;
|
||||
__export(require("./b"));
|
||||
//// [d.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
new A(); // Error
|
||||
18
tests/baselines/reference/exportNamespace1.symbols
Normal file
18
tests/baselines/reference/exportNamespace1.symbols
Normal file
@ -0,0 +1,18 @@
|
||||
=== tests/cases/conformance/externalModules/typeOnly/a.ts ===
|
||||
export class A {}
|
||||
>A : Symbol(A, Decl(a.ts, 0, 0))
|
||||
|
||||
=== tests/cases/conformance/externalModules/typeOnly/b.ts ===
|
||||
export type { A } from './a';
|
||||
>A : Symbol(A, Decl(b.ts, 0, 13))
|
||||
|
||||
=== tests/cases/conformance/externalModules/typeOnly/c.ts ===
|
||||
export * from './b';
|
||||
No type information for this code.
|
||||
No type information for this code.=== tests/cases/conformance/externalModules/typeOnly/d.ts ===
|
||||
import { A } from './c';
|
||||
>A : Symbol(A, Decl(d.ts, 0, 8))
|
||||
|
||||
new A(); // Error
|
||||
>A : Symbol(A, Decl(d.ts, 0, 8))
|
||||
|
||||
19
tests/baselines/reference/exportNamespace1.types
Normal file
19
tests/baselines/reference/exportNamespace1.types
Normal file
@ -0,0 +1,19 @@
|
||||
=== tests/cases/conformance/externalModules/typeOnly/a.ts ===
|
||||
export class A {}
|
||||
>A : A
|
||||
|
||||
=== tests/cases/conformance/externalModules/typeOnly/b.ts ===
|
||||
export type { A } from './a';
|
||||
>A : import("tests/cases/conformance/externalModules/typeOnly/a").A
|
||||
|
||||
=== tests/cases/conformance/externalModules/typeOnly/c.ts ===
|
||||
export * from './b';
|
||||
No type information for this code.
|
||||
No type information for this code.=== tests/cases/conformance/externalModules/typeOnly/d.ts ===
|
||||
import { A } from './c';
|
||||
>A : typeof A
|
||||
|
||||
new A(); // Error
|
||||
>new A() : A
|
||||
>A : typeof A
|
||||
|
||||
20
tests/baselines/reference/exportNamespace2.errors.txt
Normal file
20
tests/baselines/reference/exportNamespace2.errors.txt
Normal file
@ -0,0 +1,20 @@
|
||||
tests/cases/conformance/externalModules/typeOnly/d.ts(2,5): error TS1361: 'a' cannot be used as a value because it was imported using 'import type'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/externalModules/typeOnly/a.ts (0 errors) ====
|
||||
export class A {}
|
||||
|
||||
==== tests/cases/conformance/externalModules/typeOnly/b.ts (0 errors) ====
|
||||
export * as a from './a';
|
||||
|
||||
==== tests/cases/conformance/externalModules/typeOnly/c.ts (0 errors) ====
|
||||
import type { a } from './b';
|
||||
export { a };
|
||||
|
||||
==== tests/cases/conformance/externalModules/typeOnly/d.ts (1 errors) ====
|
||||
import { a } from './c';
|
||||
new a.A(); // Error
|
||||
~
|
||||
!!! error TS1361: 'a' cannot be used as a value because it was imported using 'import type'.
|
||||
!!! related TS1376 tests/cases/conformance/externalModules/typeOnly/c.ts:1:15: 'a' was imported here.
|
||||
|
||||
37
tests/baselines/reference/exportNamespace2.js
Normal file
37
tests/baselines/reference/exportNamespace2.js
Normal file
@ -0,0 +1,37 @@
|
||||
//// [tests/cases/conformance/externalModules/typeOnly/exportNamespace2.ts] ////
|
||||
|
||||
//// [a.ts]
|
||||
export class A {}
|
||||
|
||||
//// [b.ts]
|
||||
export * as a from './a';
|
||||
|
||||
//// [c.ts]
|
||||
import type { a } from './b';
|
||||
export { a };
|
||||
|
||||
//// [d.ts]
|
||||
import { a } from './c';
|
||||
new a.A(); // Error
|
||||
|
||||
|
||||
//// [a.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
var A = /** @class */ (function () {
|
||||
function A() {
|
||||
}
|
||||
return A;
|
||||
}());
|
||||
exports.A = A;
|
||||
//// [b.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
exports.a = require("./a");
|
||||
//// [c.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
//// [d.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
new a.A(); // Error
|
||||
24
tests/baselines/reference/exportNamespace2.symbols
Normal file
24
tests/baselines/reference/exportNamespace2.symbols
Normal file
@ -0,0 +1,24 @@
|
||||
=== tests/cases/conformance/externalModules/typeOnly/a.ts ===
|
||||
export class A {}
|
||||
>A : Symbol(A, Decl(a.ts, 0, 0))
|
||||
|
||||
=== tests/cases/conformance/externalModules/typeOnly/b.ts ===
|
||||
export * as a from './a';
|
||||
>a : Symbol(a, Decl(b.ts, 0, 11))
|
||||
|
||||
=== tests/cases/conformance/externalModules/typeOnly/c.ts ===
|
||||
import type { a } from './b';
|
||||
>a : Symbol(a, Decl(c.ts, 0, 13))
|
||||
|
||||
export { a };
|
||||
>a : Symbol(a, Decl(c.ts, 1, 8))
|
||||
|
||||
=== tests/cases/conformance/externalModules/typeOnly/d.ts ===
|
||||
import { a } from './c';
|
||||
>a : Symbol(a, Decl(d.ts, 0, 8))
|
||||
|
||||
new a.A(); // Error
|
||||
>a.A : Symbol(a.A, Decl(a.ts, 0, 0))
|
||||
>a : Symbol(a, Decl(d.ts, 0, 8))
|
||||
>A : Symbol(a.A, Decl(a.ts, 0, 0))
|
||||
|
||||
25
tests/baselines/reference/exportNamespace2.types
Normal file
25
tests/baselines/reference/exportNamespace2.types
Normal file
@ -0,0 +1,25 @@
|
||||
=== tests/cases/conformance/externalModules/typeOnly/a.ts ===
|
||||
export class A {}
|
||||
>A : A
|
||||
|
||||
=== tests/cases/conformance/externalModules/typeOnly/b.ts ===
|
||||
export * as a from './a';
|
||||
>a : typeof a
|
||||
|
||||
=== tests/cases/conformance/externalModules/typeOnly/c.ts ===
|
||||
import type { a } from './b';
|
||||
>a : any
|
||||
|
||||
export { a };
|
||||
>a : typeof a
|
||||
|
||||
=== tests/cases/conformance/externalModules/typeOnly/d.ts ===
|
||||
import { a } from './c';
|
||||
>a : typeof a
|
||||
|
||||
new a.A(); // Error
|
||||
>new a.A() : a.A
|
||||
>a.A : typeof a.A
|
||||
>a : typeof a
|
||||
>A : typeof a.A
|
||||
|
||||
18
tests/baselines/reference/exportNamespace3.errors.txt
Normal file
18
tests/baselines/reference/exportNamespace3.errors.txt
Normal file
@ -0,0 +1,18 @@
|
||||
tests/cases/conformance/externalModules/typeOnly/d.ts(2,7): error TS2339: Property 'A' does not exist on type 'typeof import("tests/cases/conformance/externalModules/typeOnly/b")'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/externalModules/typeOnly/a.ts (0 errors) ====
|
||||
export class A {}
|
||||
|
||||
==== tests/cases/conformance/externalModules/typeOnly/b.ts (0 errors) ====
|
||||
export type { A } from './a';
|
||||
|
||||
==== tests/cases/conformance/externalModules/typeOnly/c.ts (0 errors) ====
|
||||
export * as a from './b';
|
||||
|
||||
==== tests/cases/conformance/externalModules/typeOnly/d.ts (1 errors) ====
|
||||
import { a } from './c';
|
||||
new a.A(); // Error
|
||||
~
|
||||
!!! error TS2339: Property 'A' does not exist on type 'typeof import("tests/cases/conformance/externalModules/typeOnly/b")'.
|
||||
|
||||
37
tests/baselines/reference/exportNamespace3.js
Normal file
37
tests/baselines/reference/exportNamespace3.js
Normal file
@ -0,0 +1,37 @@
|
||||
//// [tests/cases/conformance/externalModules/typeOnly/exportNamespace3.ts] ////
|
||||
|
||||
//// [a.ts]
|
||||
export class A {}
|
||||
|
||||
//// [b.ts]
|
||||
export type { A } from './a';
|
||||
|
||||
//// [c.ts]
|
||||
export * as a from './b';
|
||||
|
||||
//// [d.ts]
|
||||
import { a } from './c';
|
||||
new a.A(); // Error
|
||||
|
||||
|
||||
//// [a.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
var A = /** @class */ (function () {
|
||||
function A() {
|
||||
}
|
||||
return A;
|
||||
}());
|
||||
exports.A = A;
|
||||
//// [b.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
//// [c.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
exports.a = require("./b");
|
||||
//// [d.js]
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
var c_1 = require("./c");
|
||||
new c_1.a.A(); // Error
|
||||
19
tests/baselines/reference/exportNamespace3.symbols
Normal file
19
tests/baselines/reference/exportNamespace3.symbols
Normal file
@ -0,0 +1,19 @@
|
||||
=== tests/cases/conformance/externalModules/typeOnly/a.ts ===
|
||||
export class A {}
|
||||
>A : Symbol(A, Decl(a.ts, 0, 0))
|
||||
|
||||
=== tests/cases/conformance/externalModules/typeOnly/b.ts ===
|
||||
export type { A } from './a';
|
||||
>A : Symbol(A, Decl(b.ts, 0, 13))
|
||||
|
||||
=== tests/cases/conformance/externalModules/typeOnly/c.ts ===
|
||||
export * as a from './b';
|
||||
>a : Symbol(a, Decl(c.ts, 0, 11))
|
||||
|
||||
=== tests/cases/conformance/externalModules/typeOnly/d.ts ===
|
||||
import { a } from './c';
|
||||
>a : Symbol(a, Decl(d.ts, 0, 8))
|
||||
|
||||
new a.A(); // Error
|
||||
>a : Symbol(a, Decl(d.ts, 0, 8))
|
||||
|
||||
22
tests/baselines/reference/exportNamespace3.types
Normal file
22
tests/baselines/reference/exportNamespace3.types
Normal file
@ -0,0 +1,22 @@
|
||||
=== tests/cases/conformance/externalModules/typeOnly/a.ts ===
|
||||
export class A {}
|
||||
>A : A
|
||||
|
||||
=== tests/cases/conformance/externalModules/typeOnly/b.ts ===
|
||||
export type { A } from './a';
|
||||
>A : import("tests/cases/conformance/externalModules/typeOnly/a").A
|
||||
|
||||
=== tests/cases/conformance/externalModules/typeOnly/c.ts ===
|
||||
export * as a from './b';
|
||||
>a : typeof a
|
||||
|
||||
=== tests/cases/conformance/externalModules/typeOnly/d.ts ===
|
||||
import { a } from './c';
|
||||
>a : typeof a
|
||||
|
||||
new a.A(); // Error
|
||||
>new a.A() : any
|
||||
>a.A : any
|
||||
>a : typeof a
|
||||
>A : any
|
||||
|
||||
@ -0,0 +1,12 @@
|
||||
// @Filename: a.ts
|
||||
export class A {}
|
||||
|
||||
// @Filename: b.ts
|
||||
export type { A } from './a';
|
||||
|
||||
// @Filename: c.ts
|
||||
export * from './b';
|
||||
|
||||
// @Filename: d.ts
|
||||
import { A } from './c';
|
||||
new A(); // Error
|
||||
@ -0,0 +1,13 @@
|
||||
// @Filename: a.ts
|
||||
export class A {}
|
||||
|
||||
// @Filename: b.ts
|
||||
export * as a from './a';
|
||||
|
||||
// @Filename: c.ts
|
||||
import type { a } from './b';
|
||||
export { a };
|
||||
|
||||
// @Filename: d.ts
|
||||
import { a } from './c';
|
||||
new a.A(); // Error
|
||||
@ -0,0 +1,12 @@
|
||||
// @Filename: a.ts
|
||||
export class A {}
|
||||
|
||||
// @Filename: b.ts
|
||||
export type { A } from './a';
|
||||
|
||||
// @Filename: c.ts
|
||||
export * as a from './b';
|
||||
|
||||
// @Filename: d.ts
|
||||
import { a } from './c';
|
||||
new a.A(); // Error
|
||||
Loading…
x
Reference in New Issue
Block a user