mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-04 21:53:42 -06:00
Error on export default of type: issue https://github.com/microsoft/TypeScript/issues/55087 (#55097)
Co-authored-by: eli lichtblau <elilichtblau@elis-MacBook-Pro.local> Co-authored-by: Andrew Branch <andrew@wheream.io>
This commit is contained in:
parent
c10edfbc8d
commit
9063d7b41d
@ -45846,12 +45846,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
const id = node.expression as Identifier;
|
||||
const sym = getExportSymbolOfValueSymbolIfExported(resolveEntityName(id, SymbolFlags.All, /*ignoreErrors*/ true, /*dontResolveAlias*/ true, node));
|
||||
if (sym) {
|
||||
const typeOnlyDeclaration = getTypeOnlyAliasDeclaration(sym, SymbolFlags.Value);
|
||||
markAliasReferenced(sym, id);
|
||||
// If not a value, we're interpreting the identifier as a type export, along the lines of (`export { Id as default }`)
|
||||
if (getSymbolFlags(sym) & SymbolFlags.Value) {
|
||||
// However if it is a value, we need to check it's being used correctly
|
||||
checkExpressionCached(id);
|
||||
if (!isIllegalExportDefaultInCJS && !(node.flags & NodeFlags.Ambient) && compilerOptions.verbatimModuleSyntax && getTypeOnlyAliasDeclaration(sym, SymbolFlags.Value)) {
|
||||
if (!isIllegalExportDefaultInCJS && !(node.flags & NodeFlags.Ambient) && compilerOptions.verbatimModuleSyntax && typeOnlyDeclaration) {
|
||||
error(
|
||||
id,
|
||||
node.isExportEquals
|
||||
@ -45870,6 +45871,44 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
idText(id),
|
||||
);
|
||||
}
|
||||
|
||||
if (!isIllegalExportDefaultInCJS && getIsolatedModules(compilerOptions) && !(sym.flags & SymbolFlags.Value)) {
|
||||
if (
|
||||
sym.flags & SymbolFlags.Alias
|
||||
&& resolveAlias(sym) !== unknownSymbol
|
||||
&& getSymbolFlags(sym, /*excludeTypeOnlyMeanings*/ false, /*excludeLocalMeanings*/ true) & SymbolFlags.Type
|
||||
&& (!typeOnlyDeclaration || getSourceFileOfNode(typeOnlyDeclaration) !== getSourceFileOfNode(node))
|
||||
) {
|
||||
// import { SomeType } from "./someModule";
|
||||
// export default SomeType; OR
|
||||
// export = SomeType;
|
||||
error(
|
||||
id,
|
||||
node.isExportEquals ?
|
||||
Diagnostics._0_resolves_to_a_type_and_must_be_marked_type_only_in_this_file_before_re_exporting_when_1_is_enabled_Consider_using_import_type_where_0_is_imported
|
||||
: Diagnostics._0_resolves_to_a_type_and_must_be_marked_type_only_in_this_file_before_re_exporting_when_1_is_enabled_Consider_using_export_type_0_as_default,
|
||||
idText(id),
|
||||
isolatedModulesLikeFlagName,
|
||||
);
|
||||
}
|
||||
else if (typeOnlyDeclaration && getSourceFileOfNode(typeOnlyDeclaration) !== getSourceFileOfNode(node)) {
|
||||
// import { SomeTypeOnlyValue } from "./someModule";
|
||||
// export default SomeTypeOnlyValue; OR
|
||||
// export = SomeTypeOnlyValue;
|
||||
addTypeOnlyDeclarationRelatedInfo(
|
||||
error(
|
||||
id,
|
||||
node.isExportEquals ?
|
||||
Diagnostics._0_resolves_to_a_type_only_declaration_and_must_be_marked_type_only_in_this_file_before_re_exporting_when_1_is_enabled_Consider_using_import_type_where_0_is_imported
|
||||
: Diagnostics._0_resolves_to_a_type_only_declaration_and_must_be_marked_type_only_in_this_file_before_re_exporting_when_1_is_enabled_Consider_using_export_type_0_as_default,
|
||||
idText(id),
|
||||
isolatedModulesLikeFlagName,
|
||||
),
|
||||
typeOnlyDeclaration,
|
||||
idText(id),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
checkExpressionCached(id); // doesn't resolve, check as expression to mark as error
|
||||
@ -47558,7 +47597,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
);
|
||||
case SyntaxKind.ExportAssignment:
|
||||
return (node as ExportAssignment).expression && (node as ExportAssignment).expression.kind === SyntaxKind.Identifier ?
|
||||
isAliasResolvedToValue(getSymbolOfDeclaration(node as ExportAssignment)) :
|
||||
isAliasResolvedToValue(getSymbolOfDeclaration(node as ExportAssignment), /*excludeTypeOnlyValues*/ true) :
|
||||
true;
|
||||
}
|
||||
return false;
|
||||
|
||||
@ -951,6 +951,22 @@
|
||||
"category": "Error",
|
||||
"code": 1288
|
||||
},
|
||||
"'{0}' resolves to a type-only declaration and must be marked type-only in this file before re-exporting when '{1}' is enabled. Consider using 'import type' where '{0}' is imported.": {
|
||||
"category": "Error",
|
||||
"code": 1289
|
||||
},
|
||||
"'{0}' resolves to a type-only declaration and must be marked type-only in this file before re-exporting when '{1}' is enabled. Consider using 'export type { {0} as default }'.": {
|
||||
"category": "Error",
|
||||
"code": 1290
|
||||
},
|
||||
"'{0}' resolves to a type and must be marked type-only in this file before re-exporting when '{1}' is enabled. Consider using 'import type' where '{0}' is imported.": {
|
||||
"category": "Error",
|
||||
"code": 1291
|
||||
},
|
||||
"'{0}' resolves to a type and must be marked type-only in this file before re-exporting when '{1}' is enabled. Consider using 'export type { {0} as default }'.": {
|
||||
"category": "Error",
|
||||
"code": 1292
|
||||
},
|
||||
|
||||
"'with' statements are not allowed in an async function block.": {
|
||||
"category": "Error",
|
||||
|
||||
@ -12,4 +12,11 @@
|
||||
~
|
||||
!!! error TS1362: 'A' cannot be used as a value because it was exported using 'export type'.
|
||||
!!! related TS1377 /a.ts:2:15: 'A' was exported here.
|
||||
|
||||
|
||||
==== /c.ts (0 errors) ====
|
||||
import type { A } from './a';
|
||||
export = A;
|
||||
|
||||
==== /d.ts (0 errors) ====
|
||||
import { A } from './a';
|
||||
export = A;
|
||||
@ -9,6 +9,13 @@ import { A } from './a';
|
||||
declare const a: A;
|
||||
new A();
|
||||
|
||||
//// [c.ts]
|
||||
import type { A } from './a';
|
||||
export = A;
|
||||
|
||||
//// [d.ts]
|
||||
import { A } from './a';
|
||||
export = A;
|
||||
|
||||
//// [a.js]
|
||||
"use strict";
|
||||
@ -22,3 +29,9 @@ var A = /** @class */ (function () {
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
new A();
|
||||
//// [c.js]
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
//// [d.js]
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
@ -18,3 +18,17 @@ declare const a: A;
|
||||
new A();
|
||||
>A : Symbol(A, Decl(b.ts, 0, 8))
|
||||
|
||||
=== /c.ts ===
|
||||
import type { A } from './a';
|
||||
>A : Symbol(A, Decl(c.ts, 0, 13))
|
||||
|
||||
export = A;
|
||||
>A : Symbol(A, Decl(c.ts, 0, 13))
|
||||
|
||||
=== /d.ts ===
|
||||
import { A } from './a';
|
||||
>A : Symbol(A, Decl(d.ts, 0, 8))
|
||||
|
||||
export = A;
|
||||
>A : Symbol(A, Decl(d.ts, 0, 8))
|
||||
|
||||
@ -18,3 +18,17 @@ new A();
|
||||
>new A() : A
|
||||
>A : typeof A
|
||||
|
||||
=== /c.ts ===
|
||||
import type { A } from './a';
|
||||
>A : A
|
||||
|
||||
export = A;
|
||||
>A : A
|
||||
|
||||
=== /d.ts ===
|
||||
import { A } from './a';
|
||||
>A : typeof A
|
||||
|
||||
export = A;
|
||||
>A : A
|
||||
|
||||
@ -0,0 +1,25 @@
|
||||
/b.ts(3,5): error TS1362: 'A' cannot be used as a value because it was exported using 'export type'.
|
||||
/d.ts(2,10): error TS1291: 'A' resolves to a type and must be marked type-only in this file before re-exporting when 'isolatedModules' is enabled. Consider using 'import type' where 'A' is imported.
|
||||
|
||||
|
||||
==== /a.ts (0 errors) ====
|
||||
class A {}
|
||||
export type { A };
|
||||
|
||||
==== /b.ts (1 errors) ====
|
||||
import { A } from './a';
|
||||
declare const a: A;
|
||||
new A();
|
||||
~
|
||||
!!! error TS1362: 'A' cannot be used as a value because it was exported using 'export type'.
|
||||
!!! related TS1377 /a.ts:2:15: 'A' was exported here.
|
||||
|
||||
==== /c.ts (0 errors) ====
|
||||
import type { A } from './a';
|
||||
export = A;
|
||||
|
||||
==== /d.ts (1 errors) ====
|
||||
import { A } from './a';
|
||||
export = A;
|
||||
~
|
||||
!!! error TS1291: 'A' resolves to a type and must be marked type-only in this file before re-exporting when 'isolatedModules' is enabled. Consider using 'import type' where 'A' is imported.
|
||||
@ -0,0 +1,37 @@
|
||||
//// [tests/cases/conformance/externalModules/typeOnly/exportDeclaration.ts] ////
|
||||
|
||||
//// [a.ts]
|
||||
class A {}
|
||||
export type { A };
|
||||
|
||||
//// [b.ts]
|
||||
import { A } from './a';
|
||||
declare const a: A;
|
||||
new A();
|
||||
|
||||
//// [c.ts]
|
||||
import type { A } from './a';
|
||||
export = A;
|
||||
|
||||
//// [d.ts]
|
||||
import { A } from './a';
|
||||
export = A;
|
||||
|
||||
//// [a.js]
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var A = /** @class */ (function () {
|
||||
function A() {
|
||||
}
|
||||
return A;
|
||||
}());
|
||||
//// [b.js]
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
new A();
|
||||
//// [c.js]
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
//// [d.js]
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
@ -0,0 +1,34 @@
|
||||
//// [tests/cases/conformance/externalModules/typeOnly/exportDeclaration.ts] ////
|
||||
|
||||
=== /a.ts ===
|
||||
class A {}
|
||||
>A : Symbol(A, Decl(a.ts, 0, 0))
|
||||
|
||||
export type { A };
|
||||
>A : Symbol(A, Decl(a.ts, 1, 13))
|
||||
|
||||
=== /b.ts ===
|
||||
import { A } from './a';
|
||||
>A : Symbol(A, Decl(b.ts, 0, 8))
|
||||
|
||||
declare const a: A;
|
||||
>a : Symbol(a, Decl(b.ts, 1, 13))
|
||||
>A : Symbol(A, Decl(b.ts, 0, 8))
|
||||
|
||||
new A();
|
||||
>A : Symbol(A, Decl(b.ts, 0, 8))
|
||||
|
||||
=== /c.ts ===
|
||||
import type { A } from './a';
|
||||
>A : Symbol(A, Decl(c.ts, 0, 13))
|
||||
|
||||
export = A;
|
||||
>A : Symbol(A, Decl(c.ts, 0, 13))
|
||||
|
||||
=== /d.ts ===
|
||||
import { A } from './a';
|
||||
>A : Symbol(A, Decl(d.ts, 0, 8))
|
||||
|
||||
export = A;
|
||||
>A : Symbol(A, Decl(d.ts, 0, 8))
|
||||
|
||||
@ -0,0 +1,34 @@
|
||||
//// [tests/cases/conformance/externalModules/typeOnly/exportDeclaration.ts] ////
|
||||
|
||||
=== /a.ts ===
|
||||
class A {}
|
||||
>A : A
|
||||
|
||||
export type { A };
|
||||
>A : A
|
||||
|
||||
=== /b.ts ===
|
||||
import { A } from './a';
|
||||
>A : typeof A
|
||||
|
||||
declare const a: A;
|
||||
>a : A
|
||||
|
||||
new A();
|
||||
>new A() : A
|
||||
>A : typeof A
|
||||
|
||||
=== /c.ts ===
|
||||
import type { A } from './a';
|
||||
>A : A
|
||||
|
||||
export = A;
|
||||
>A : A
|
||||
|
||||
=== /d.ts ===
|
||||
import { A } from './a';
|
||||
>A : typeof A
|
||||
|
||||
export = A;
|
||||
>A : A
|
||||
|
||||
@ -41,7 +41,6 @@ exports.A = A;
|
||||
//// [b.js]
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.default = types;
|
||||
//// [c.js]
|
||||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
|
||||
@ -40,7 +40,7 @@ var A = /** @class */ (function () {
|
||||
exports.A = A;
|
||||
//// [b.js]
|
||||
"use strict";
|
||||
module.exports = types;
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
//// [c.js]
|
||||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
|
||||
@ -0,0 +1,36 @@
|
||||
/test1.ts(1,10): error TS2865: Import 'T' conflicts with local value, so must be declared with a type-only import when 'isolatedModules' is enabled.
|
||||
/test2.ts(1,10): error TS2440: Import declaration conflicts with local declaration of 'T'.
|
||||
/test2.ts(3,16): error TS1292: 'T' resolves to a type and must be marked type-only in this file before re-exporting when 'isolatedModules' is enabled. Consider using 'export type { T as default }'.
|
||||
/test3.ts(2,16): error TS1292: 'T' resolves to a type and must be marked type-only in this file before re-exporting when 'isolatedModules' is enabled. Consider using 'export type { T as default }'.
|
||||
|
||||
|
||||
==== /type.ts (0 errors) ====
|
||||
export type T = number;
|
||||
|
||||
==== /test1.ts (1 errors) ====
|
||||
import { T } from "./type";
|
||||
~
|
||||
!!! error TS2865: Import 'T' conflicts with local value, so must be declared with a type-only import when 'isolatedModules' is enabled.
|
||||
const T = 0; // Error as of #56354
|
||||
export default T; // Ok
|
||||
|
||||
==== /test2.ts (2 errors) ====
|
||||
import { T } from "./type";
|
||||
~
|
||||
!!! error TS2440: Import declaration conflicts with local declaration of 'T'.
|
||||
type T = number; // Merge error
|
||||
export default T; // Transpiler could assume the alias resolves to a value?
|
||||
~
|
||||
!!! error TS1292: 'T' resolves to a type and must be marked type-only in this file before re-exporting when 'isolatedModules' is enabled. Consider using 'export type { T as default }'.
|
||||
|
||||
==== /test3.ts (1 errors) ====
|
||||
import { T } from "./type";
|
||||
export default T; // Error
|
||||
~
|
||||
!!! error TS1292: 'T' resolves to a type and must be marked type-only in this file before re-exporting when 'isolatedModules' is enabled. Consider using 'export type { T as default }'.
|
||||
|
||||
==== /test4.ts (0 errors) ====
|
||||
// @ts-expect-error
|
||||
import unresolved from "./doesntexist";
|
||||
export default unresolved;
|
||||
|
||||
@ -0,0 +1,45 @@
|
||||
//// [tests/cases/compiler/isolatedModulesExportDeclarationType.ts] ////
|
||||
|
||||
//// [type.ts]
|
||||
export type T = number;
|
||||
|
||||
//// [test1.ts]
|
||||
import { T } from "./type";
|
||||
const T = 0; // Error as of #56354
|
||||
export default T; // Ok
|
||||
|
||||
//// [test2.ts]
|
||||
import { T } from "./type";
|
||||
type T = number; // Merge error
|
||||
export default T; // Transpiler could assume the alias resolves to a value?
|
||||
|
||||
//// [test3.ts]
|
||||
import { T } from "./type";
|
||||
export default T; // Error
|
||||
|
||||
//// [test4.ts]
|
||||
// @ts-expect-error
|
||||
import unresolved from "./doesntexist";
|
||||
export default unresolved;
|
||||
|
||||
|
||||
//// [type.js]
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
//// [test1.js]
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var T = 0; // Error as of #56354
|
||||
exports.default = T; // Ok
|
||||
//// [test2.js]
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
//// [test3.js]
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
//// [test4.js]
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
// @ts-expect-error
|
||||
var doesntexist_1 = require("./doesntexist");
|
||||
exports.default = doesntexist_1.default;
|
||||
24
tests/cases/compiler/isolatedModulesExportDeclarationType.ts
Normal file
24
tests/cases/compiler/isolatedModulesExportDeclarationType.ts
Normal file
@ -0,0 +1,24 @@
|
||||
// @isolatedModules: true
|
||||
// @noTypesAndSymbols: true
|
||||
|
||||
// @Filename: /type.ts
|
||||
export type T = number;
|
||||
|
||||
// @Filename: /test1.ts
|
||||
import { T } from "./type";
|
||||
const T = 0; // Error as of #56354
|
||||
export default T; // Ok
|
||||
|
||||
// @Filename: /test2.ts
|
||||
import { T } from "./type";
|
||||
type T = number; // Merge error
|
||||
export default T; // Transpiler could assume the alias resolves to a value?
|
||||
|
||||
// @Filename: /test3.ts
|
||||
import { T } from "./type";
|
||||
export default T; // Error
|
||||
|
||||
// @Filename: /test4.ts
|
||||
// @ts-expect-error
|
||||
import unresolved from "./doesntexist";
|
||||
export default unresolved;
|
||||
@ -1,3 +1,6 @@
|
||||
// @module: commonjs
|
||||
// @isolatedModules: false, true
|
||||
|
||||
// @Filename: /a.ts
|
||||
class A {}
|
||||
export type { A };
|
||||
@ -6,3 +9,11 @@ export type { A };
|
||||
import { A } from './a';
|
||||
declare const a: A;
|
||||
new A();
|
||||
|
||||
// @Filename: /c.ts
|
||||
import type { A } from './a';
|
||||
export = A;
|
||||
|
||||
// @Filename: /d.ts
|
||||
import { A } from './a';
|
||||
export = A;
|
||||
Loading…
x
Reference in New Issue
Block a user