diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 5af10d2b76808..64bc3c084d444 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1537,9 +1537,9 @@ namespace ts { return symbol; } if (symbol.flags & SymbolFlags.Alias) { - const target = resolveAlias(symbol); - // Unknown symbol means an error occurred in alias resolution, treat it as positive answer to avoid cascading errors - if (target === unknownSymbol || target.flags & meaning) { + const targetFlags = getAllSymbolFlags(symbol); + // `targetFlags` will be `SymbolFlags.All` if an error occurred in alias resolution; this avoids cascading errors + if (targetFlags & meaning) { return symbol; } } @@ -2226,8 +2226,8 @@ namespace ts { !checkAndReportErrorForExtendingInterface(errorLocation) && !checkAndReportErrorForUsingTypeAsNamespace(errorLocation, name, meaning) && !checkAndReportErrorForExportingPrimitiveType(errorLocation, name) && + !checkAndReportErrorForUsingNamespaceAsTypeOrValue(errorLocation, name, meaning) && !checkAndReportErrorForUsingTypeAsValue(errorLocation, name, meaning) && - !checkAndReportErrorForUsingNamespaceModuleAsValue(errorLocation, name, meaning) && !checkAndReportErrorForUsingValueAsType(errorLocation, name, meaning)) { let suggestion: Symbol | undefined; let suggestedLib: string | undefined; @@ -2320,7 +2320,7 @@ namespace ts { } } if (result && errorLocation && meaning & SymbolFlags.Value && result.flags & SymbolFlags.Alias && !(result.flags & SymbolFlags.Value) && !isValidTypeOnlyAliasUseSite(errorLocation)) { - const typeOnlyDeclaration = getTypeOnlyAliasDeclaration(result); + const typeOnlyDeclaration = getTypeOnlyAliasDeclaration(result, SymbolFlags.Value); if (typeOnlyDeclaration) { const message = typeOnlyDeclaration.kind === SyntaxKind.ExportSpecifier ? Diagnostics._0_cannot_be_used_as_a_value_because_it_was_exported_using_export_type @@ -2515,7 +2515,7 @@ namespace ts { } function checkAndReportErrorForUsingTypeAsValue(errorLocation: Node, name: __String, meaning: SymbolFlags): boolean { - if (meaning & (SymbolFlags.Value & ~SymbolFlags.NamespaceModule)) { + if (meaning & SymbolFlags.Value) { if (isPrimitiveTypeName(name)) { if (isExtendedByInterface(errorLocation)) { error(errorLocation, Diagnostics.An_interface_cannot_extend_a_primitive_type_like_0_an_interface_can_only_extend_named_types_and_classes, unescapeLeadingUnderscores(name)); @@ -2526,7 +2526,8 @@ namespace ts { return true; } const symbol = resolveSymbol(resolveName(errorLocation, name, SymbolFlags.Type & ~SymbolFlags.Value, /*nameNotFoundMessage*/undefined, /*nameArg*/ undefined, /*isUse*/ false)); - if (symbol && !(symbol.flags & SymbolFlags.NamespaceModule)) { + const allFlags = symbol && getAllSymbolFlags(symbol); + if (symbol && allFlags !== undefined && !(allFlags & SymbolFlags.Value)) { const rawName = unescapeLeadingUnderscores(name); if (isES2015OrLaterConstructorName(name)) { error(errorLocation, Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_value_here_Do_you_need_to_change_your_target_library_Try_changing_the_lib_compiler_option_to_es2015_or_later, rawName); @@ -2577,9 +2578,9 @@ namespace ts { return false; } - function checkAndReportErrorForUsingNamespaceModuleAsValue(errorLocation: Node, name: __String, meaning: SymbolFlags): boolean { - if (meaning & (SymbolFlags.Value & ~SymbolFlags.NamespaceModule & ~SymbolFlags.Type)) { - const symbol = resolveSymbol(resolveName(errorLocation, name, SymbolFlags.NamespaceModule & ~SymbolFlags.Value, /*nameNotFoundMessage*/undefined, /*nameArg*/ undefined, /*isUse*/ false)); + function checkAndReportErrorForUsingNamespaceAsTypeOrValue(errorLocation: Node, name: __String, meaning: SymbolFlags): boolean { + if (meaning & (SymbolFlags.Value & ~SymbolFlags.Type)) { + const symbol = resolveSymbol(resolveName(errorLocation, name, SymbolFlags.NamespaceModule, /*nameNotFoundMessage*/undefined, /*nameArg*/ undefined, /*isUse*/ false)); if (symbol) { error( errorLocation, @@ -2588,8 +2589,8 @@ namespace ts { return true; } } - else if (meaning & (SymbolFlags.Type & ~SymbolFlags.NamespaceModule & ~SymbolFlags.Value)) { - const symbol = resolveSymbol(resolveName(errorLocation, name, (SymbolFlags.ValueModule | SymbolFlags.NamespaceModule) & ~SymbolFlags.Type, /*nameNotFoundMessage*/undefined, /*nameArg*/ undefined, /*isUse*/ false)); + else if (meaning & (SymbolFlags.Type & ~SymbolFlags.Value)) { + const symbol = resolveSymbol(resolveName(errorLocation, name, SymbolFlags.Module, /*nameNotFoundMessage*/undefined, /*nameArg*/ undefined, /*isUse*/ false)); if (symbol) { error(errorLocation, Diagnostics.Cannot_use_namespace_0_as_a_type, unescapeLeadingUnderscores(name)); return true; @@ -3237,6 +3238,54 @@ namespace ts { return undefined; } + /** + * Gets combined flags of a `symbol` and all alias targets it resolves to. `resolveAlias` + * is typically recursive over chains of aliases, but stops mid-chain if an alias is merged + * with another exported symbol, e.g. + * ```ts + * // a.ts + * export const a = 0; + * // b.ts + * export { a } from "./a"; + * export type a = number; + * // c.ts + * import { a } from "./b"; + * ``` + * Calling `resolveAlias` on the `a` in c.ts would stop at the merged symbol exported + * from b.ts, even though there is still more alias to resolve. Consequently, if we were + * trying to determine if the `a` in c.ts has a value meaning, looking at the flags on + * the local symbol and on the symbol returned by `resolveAlias` is not enough. + * @returns SymbolFlags.All if `symbol` is an alias that ultimately resolves to `unknown`; + * combined flags of all alias targets otherwise. + */ + function getAllSymbolFlags(symbol: Symbol): SymbolFlags { + let flags = symbol.flags; + let seenSymbols; + while (symbol.flags & SymbolFlags.Alias) { + const target = resolveAlias(symbol); + if (target === unknownSymbol) { + return SymbolFlags.All; + } + + // Optimizations - try to avoid creating or adding to + // `seenSymbols` if possible + if (target === symbol || seenSymbols?.has(target)) { + break; + } + if (target.flags & SymbolFlags.Alias) { + if (seenSymbols) { + seenSymbols.add(target); + } + else { + seenSymbols = new Set([symbol, target]); + } + } + flags |= target.flags; + symbol = target; + } + return flags; + } + /** * Marks a symbol as type-only if its declaration is syntactically type-only. * If it is not itself marked type-only, but resolves to a type-only alias @@ -3289,12 +3338,18 @@ namespace ts { } /** Indicates that a symbol directly or indirectly resolves to a type-only import or export. */ - function getTypeOnlyAliasDeclaration(symbol: Symbol): TypeOnlyAliasDeclaration | undefined { + function getTypeOnlyAliasDeclaration(symbol: Symbol, include?: SymbolFlags): TypeOnlyAliasDeclaration | undefined { if (!(symbol.flags & SymbolFlags.Alias)) { return undefined; } const links = getSymbolLinks(symbol); - return links.typeOnlyDeclaration || undefined; + if (include === undefined) { + return links.typeOnlyDeclaration || undefined; + } + if (links.typeOnlyDeclaration) { + return getAllSymbolFlags(resolveAlias(links.typeOnlyDeclaration.symbol)) & include ? links.typeOnlyDeclaration : undefined; + } + return undefined; } function markExportAsReferenced(node: ImportEqualsDeclaration | ExportSpecifier) { @@ -3302,7 +3357,7 @@ namespace ts { const target = resolveAlias(symbol); if (target) { const markAlias = target === unknownSymbol || - ((target.flags & SymbolFlags.Value) && !isConstEnumOrConstEnumOnlyModule(target) && !getTypeOnlyAliasDeclaration(symbol)); + ((getAllSymbolFlags(target) & SymbolFlags.Value) && !isConstEnumOrConstEnumOnlyModule(target) && !getTypeOnlyAliasDeclaration(symbol, SymbolFlags.Value)); if (markAlias) { markAliasSymbolAsReferenced(symbol); @@ -3323,8 +3378,7 @@ namespace ts { // This way a chain of imports can be elided if ultimately the final input is only used in a type // position. if (isInternalModuleImportEqualsDeclaration(node)) { - const target = resolveSymbol(symbol); - if (target === unknownSymbol || target.flags & SymbolFlags.Value) { + if (getAllSymbolFlags(resolveSymbol(symbol)) & SymbolFlags.Value) { // import foo = checkExpressionCached(node.moduleReference as Expression); } @@ -4250,7 +4304,7 @@ namespace ts { function symbolIsValue(symbol: Symbol, includeTypeOnlyMembers?: boolean): boolean { return !!( symbol.flags & SymbolFlags.Value || - symbol.flags & SymbolFlags.Alias && resolveAlias(symbol).flags & SymbolFlags.Value && (includeTypeOnlyMembers || !getTypeOnlyAliasDeclaration(symbol))); + symbol.flags & SymbolFlags.Alias && getAllSymbolFlags(symbol) & SymbolFlags.Value && (includeTypeOnlyMembers || !getTypeOnlyAliasDeclaration(symbol))); } function findConstructorDeclaration(node: ClassLikeDeclaration): ConstructorDeclaration | undefined { @@ -4544,8 +4598,10 @@ namespace ts { } // Qualify if the symbol from symbol table has same meaning as expected - symbolFromSymbolTable = (symbolFromSymbolTable.flags & SymbolFlags.Alias && !getDeclarationOfKind(symbolFromSymbolTable, SyntaxKind.ExportSpecifier)) ? resolveAlias(symbolFromSymbolTable) : symbolFromSymbolTable; - if (symbolFromSymbolTable.flags & meaning) { + const shouldResolveAlias = (symbolFromSymbolTable.flags & SymbolFlags.Alias && !getDeclarationOfKind(symbolFromSymbolTable, SyntaxKind.ExportSpecifier)); + symbolFromSymbolTable = shouldResolveAlias ? resolveAlias(symbolFromSymbolTable) : symbolFromSymbolTable; + const flags = shouldResolveAlias ? getAllSymbolFlags(symbolFromSymbolTable) : symbolFromSymbolTable.flags; + if (flags & meaning) { qualify = true; return true; } @@ -7519,7 +7575,7 @@ namespace ts { } function isTypeOnlyNamespace(symbol: Symbol) { - return every(getNamespaceMembersForSerialization(symbol), m => !(resolveSymbol(m).flags & SymbolFlags.Value)); + return every(getNamespaceMembersForSerialization(symbol), m => !(getAllSymbolFlags(resolveSymbol(m)) & SymbolFlags.Value)); } function serializeModule(symbol: Symbol, symbolName: string, modifierFlags: ModifierFlags) { @@ -10017,7 +10073,7 @@ namespace ts { links.type = exportSymbol?.declarations && isDuplicatedCommonJSExport(exportSymbol.declarations) && symbol.declarations!.length ? getFlowTypeFromCommonJSExport(exportSymbol) : isDuplicatedCommonJSExport(symbol.declarations) ? autoType : declaredType ? declaredType - : targetSymbol.flags & SymbolFlags.Value ? getTypeOfSymbol(targetSymbol) + : getAllSymbolFlags(targetSymbol) & SymbolFlags.Value ? getTypeOfSymbol(targetSymbol) : errorType; } return links.type; @@ -25965,9 +26021,9 @@ namespace ts { } function markAliasReferenced(symbol: Symbol, location: Node) { - if (isNonLocalAlias(symbol, /*excludes*/ SymbolFlags.Value) && !isInTypeQuery(location) && !getTypeOnlyAliasDeclaration(symbol)) { + if (isNonLocalAlias(symbol, /*excludes*/ SymbolFlags.Value) && !isInTypeQuery(location) && !getTypeOnlyAliasDeclaration(symbol, SymbolFlags.Value)) { const target = resolveAlias(symbol); - if (target.flags & SymbolFlags.Value) { + if (getAllSymbolFlags(target) & SymbolFlags.Value) { // An alias resolving to a const enum cannot be elided if (1) 'isolatedModules' is enabled // (because the const enum value will not be inlined), or if (2) the alias is an export // of a const enum declaration that will be preserved. @@ -32514,7 +32570,7 @@ namespace ts { if (symbol && symbol.flags & SymbolFlags.Alias) { symbol = resolveAlias(symbol); } - return !!(symbol && (symbol.flags & SymbolFlags.Enum) && getEnumKind(symbol) === EnumKind.Literal); + return !!(symbol && (getAllSymbolFlags(symbol) & SymbolFlags.Enum) && getEnumKind(symbol) === EnumKind.Literal); } return false; } @@ -41444,11 +41500,12 @@ namespace ts { return; } + const targetFlags = getAllSymbolFlags(target); const excludedMeanings = (symbol.flags & (SymbolFlags.Value | SymbolFlags.ExportValue) ? SymbolFlags.Value : 0) | (symbol.flags & SymbolFlags.Type ? SymbolFlags.Type : 0) | (symbol.flags & SymbolFlags.Namespace ? SymbolFlags.Namespace : 0); - if (target.flags & excludedMeanings) { + if (targetFlags & excludedMeanings) { const message = node.kind === SyntaxKind.ExportSpecifier ? Diagnostics.Export_declaration_conflicts_with_exported_declaration_of_0 : Diagnostics.Import_declaration_conflicts_with_local_declaration_of_0; @@ -41459,7 +41516,7 @@ namespace ts { && !isTypeOnlyImportOrExportDeclaration(node) && !(node.flags & NodeFlags.Ambient)) { const typeOnlyAlias = getTypeOnlyAliasDeclaration(symbol); - const isType = !(target.flags & SymbolFlags.Value); + const isType = !(targetFlags & SymbolFlags.Value); if (isType || typeOnlyAlias) { switch (node.kind) { case SyntaxKind.ImportClause: @@ -41637,14 +41694,15 @@ namespace ts { if (node.moduleReference.kind !== SyntaxKind.ExternalModuleReference) { const target = resolveAlias(getSymbolOfNode(node)); if (target !== unknownSymbol) { - if (target.flags & SymbolFlags.Value) { + const targetFlags = getAllSymbolFlags(target); + if (targetFlags & SymbolFlags.Value) { // Target is a value symbol, check that it is not hidden by a local declaration with the same name const moduleName = getFirstIdentifier(node.moduleReference); if (!(resolveEntityName(moduleName, SymbolFlags.Value | SymbolFlags.Namespace)!.flags & SymbolFlags.Namespace)) { error(moduleName, Diagnostics.Module_0_is_hidden_by_a_local_declaration_with_the_same_name, declarationNameToString(moduleName)); } } - if (target.flags & SymbolFlags.Type) { + if (targetFlags & SymbolFlags.Type) { checkTypeNameIsReserved(node.name, Diagnostics.Import_name_cannot_be_0); } } @@ -41795,7 +41853,7 @@ namespace ts { markExportAsReferenced(node); } const target = symbol && (symbol.flags & SymbolFlags.Alias ? resolveAlias(symbol) : symbol); - if (!target || target === unknownSymbol || target.flags & SymbolFlags.Value) { + if (!target || getAllSymbolFlags(target) & SymbolFlags.Value) { checkExpressionCached(node.propertyName || node.name); } } @@ -41847,7 +41905,7 @@ namespace ts { markAliasReferenced(sym, id); // If not a value, we're interpreting the identifier as a type export, along the lines of (`export { Id as default }`) const target = sym.flags & SymbolFlags.Alias ? resolveAlias(sym) : sym; - if (target === unknownSymbol || target.flags & SymbolFlags.Value) { + if (getAllSymbolFlags(target) & SymbolFlags.Value) { // However if it is a value, we need to check it's being used correctly checkExpressionCached(node.expression); } @@ -43305,7 +43363,7 @@ namespace ts { function isValue(s: Symbol): boolean { s = resolveSymbol(s); - return s && !!(s.flags & SymbolFlags.Value); + return s && !!(getAllSymbolFlags(s) & SymbolFlags.Value); } } @@ -43361,7 +43419,7 @@ namespace ts { // We should only get the declaration of an alias if there isn't a local value // declaration for the symbol - if (isNonLocalAlias(symbol, /*excludes*/ SymbolFlags.Value) && !getTypeOnlyAliasDeclaration(symbol)) { + if (isNonLocalAlias(symbol, /*excludes*/ SymbolFlags.Value) && !getTypeOnlyAliasDeclaration(symbol, SymbolFlags.Value)) { return getDeclarationOfAliasSymbol(symbol); } } @@ -43458,7 +43516,7 @@ namespace ts { case SyntaxKind.ImportSpecifier: case SyntaxKind.ExportSpecifier: const symbol = getSymbolOfNode(node); - return !!symbol && isAliasResolvedToValue(symbol) && !getTypeOnlyAliasDeclaration(symbol); + return !!symbol && isAliasResolvedToValue(symbol) && !getTypeOnlyAliasDeclaration(symbol, SymbolFlags.Value); case SyntaxKind.ExportDeclaration: const exportClause = (node as ExportDeclaration).exportClause; return !!exportClause && ( @@ -43494,7 +43552,7 @@ namespace ts { } // const enums and modules that contain only const enums are not considered values from the emit perspective // unless 'preserveConstEnums' option is set to true - return !!(target.flags & SymbolFlags.Value) && + return !!((getAllSymbolFlags(target) ?? -1) & SymbolFlags.Value) && (shouldPreserveConstEnums(compilerOptions) || !isConstEnumOrConstEnumOnlyModule(target)); } @@ -43511,7 +43569,7 @@ namespace ts { } const target = getSymbolLinks(symbol!).aliasTarget; // TODO: GH#18217 if (target && getEffectiveModifierFlags(node) & ModifierFlags.Export && - target.flags & SymbolFlags.Value && + getAllSymbolFlags(target) & SymbolFlags.Value && (shouldPreserveConstEnums(compilerOptions) || !isConstEnumOrConstEnumOnlyModule(target))) { // An `export import ... =` of a value symbol is always considered referenced return true; diff --git a/tests/baselines/reference/allowImportClausesToMergeWithTypes.errors.txt b/tests/baselines/reference/allowImportClausesToMergeWithTypes.errors.txt index 63cb28ea7d626..864ac1e6335bc 100644 --- a/tests/baselines/reference/allowImportClausesToMergeWithTypes.errors.txt +++ b/tests/baselines/reference/allowImportClausesToMergeWithTypes.errors.txt @@ -1,4 +1,3 @@ -tests/cases/compiler/index.ts(4,1): error TS2693: 'zzz' only refers to a type, but is being used as a value here. tests/cases/compiler/index.ts(9,10): error TS2749: 'originalZZZ' refers to a value, but is being used as a type here. Did you mean 'typeof originalZZZ'? @@ -18,13 +17,11 @@ tests/cases/compiler/index.ts(9,10): error TS2749: 'originalZZZ' refers to a val export { zzz as default }; -==== tests/cases/compiler/index.ts (2 errors) ==== +==== tests/cases/compiler/index.ts (1 errors) ==== import zzz from "./a"; const x: zzz = { x: "" }; zzz; - ~~~ -!!! error TS2693: 'zzz' only refers to a type, but is being used as a value here. import originalZZZ from "./b"; originalZZZ; diff --git a/tests/baselines/reference/allowImportClausesToMergeWithTypes.js b/tests/baselines/reference/allowImportClausesToMergeWithTypes.js index 8c171dbfceae3..fa9e5407b7884 100644 --- a/tests/baselines/reference/allowImportClausesToMergeWithTypes.js +++ b/tests/baselines/reference/allowImportClausesToMergeWithTypes.js @@ -44,6 +44,7 @@ b_1["default"]; //// [index.js] "use strict"; exports.__esModule = true; +var a_1 = require("./a"); var x = { x: "" }; a_1["default"]; var b_1 = require("./b"); diff --git a/tests/baselines/reference/allowImportClausesToMergeWithTypes.symbols b/tests/baselines/reference/allowImportClausesToMergeWithTypes.symbols index 769ec5574c18e..af6bdfccb99cb 100644 --- a/tests/baselines/reference/allowImportClausesToMergeWithTypes.symbols +++ b/tests/baselines/reference/allowImportClausesToMergeWithTypes.symbols @@ -38,6 +38,7 @@ const x: zzz = { x: "" }; >x : Symbol(x, Decl(index.ts, 2, 16)) zzz; +>zzz : Symbol(zzz, Decl(index.ts, 0, 6)) import originalZZZ from "./b"; >originalZZZ : Symbol(originalZZZ, Decl(index.ts, 5, 6)) diff --git a/tests/baselines/reference/allowImportClausesToMergeWithTypes.types b/tests/baselines/reference/allowImportClausesToMergeWithTypes.types index e153d2fa23302..1848fcb9fe52b 100644 --- a/tests/baselines/reference/allowImportClausesToMergeWithTypes.types +++ b/tests/baselines/reference/allowImportClausesToMergeWithTypes.types @@ -30,7 +30,7 @@ export { zzz as default }; === tests/cases/compiler/index.ts === import zzz from "./a"; ->zzz : any +>zzz : 123 const x: zzz = { x: "" }; >x : zzz @@ -39,7 +39,7 @@ const x: zzz = { x: "" }; >"" : "" zzz; ->zzz : any +>zzz : 123 import originalZZZ from "./b"; >originalZZZ : 123 diff --git a/tests/baselines/reference/importElisionConstEnumMerge1.errors.txt b/tests/baselines/reference/importElisionConstEnumMerge1.errors.txt new file mode 100644 index 0000000000000..2d3b712f8720a --- /dev/null +++ b/tests/baselines/reference/importElisionConstEnumMerge1.errors.txt @@ -0,0 +1,21 @@ +tests/cases/conformance/constEnums/merge.ts(1,10): error TS2440: Import declaration conflicts with local declaration of 'Enum'. + + +==== tests/cases/conformance/constEnums/enum.ts (0 errors) ==== + export const enum Enum { + One = 1, + } + +==== tests/cases/conformance/constEnums/merge.ts (1 errors) ==== + import { Enum } from "./enum"; + ~~~~ +!!! error TS2440: Import declaration conflicts with local declaration of 'Enum'. + namespace Enum { + export type Foo = number; + } + export { Enum }; + +==== tests/cases/conformance/constEnums/index.ts (0 errors) ==== + import { Enum } from "./merge"; + Enum.One; + \ No newline at end of file diff --git a/tests/baselines/reference/importElisionConstEnumMerge1.js b/tests/baselines/reference/importElisionConstEnumMerge1.js new file mode 100644 index 0000000000000..3e63187bcc39d --- /dev/null +++ b/tests/baselines/reference/importElisionConstEnumMerge1.js @@ -0,0 +1,31 @@ +//// [tests/cases/conformance/constEnums/importElisionConstEnumMerge1.ts] //// + +//// [enum.ts] +export const enum Enum { + One = 1, +} + +//// [merge.ts] +import { Enum } from "./enum"; +namespace Enum { + export type Foo = number; +} +export { Enum }; + +//// [index.ts] +import { Enum } from "./merge"; +Enum.One; + + +//// [enum.js] +"use strict"; +exports.__esModule = true; +//// [merge.js] +"use strict"; +exports.__esModule = true; +exports.Enum = void 0; +//// [index.js] +"use strict"; +exports.__esModule = true; +var merge_1 = require("./merge"); +1 /* Enum.One */; diff --git a/tests/baselines/reference/importElisionConstEnumMerge1.symbols b/tests/baselines/reference/importElisionConstEnumMerge1.symbols new file mode 100644 index 0000000000000..c8d5232899a32 --- /dev/null +++ b/tests/baselines/reference/importElisionConstEnumMerge1.symbols @@ -0,0 +1,30 @@ +=== tests/cases/conformance/constEnums/enum.ts === +export const enum Enum { +>Enum : Symbol(Enum, Decl(enum.ts, 0, 0)) + + One = 1, +>One : Symbol(Enum.One, Decl(enum.ts, 0, 24)) +} + +=== tests/cases/conformance/constEnums/merge.ts === +import { Enum } from "./enum"; +>Enum : Symbol(Enum, Decl(merge.ts, 0, 8), Decl(merge.ts, 0, 30)) + +namespace Enum { +>Enum : Symbol(Enum, Decl(merge.ts, 0, 8), Decl(merge.ts, 0, 30)) + + export type Foo = number; +>Foo : Symbol(Foo, Decl(merge.ts, 1, 16)) +} +export { Enum }; +>Enum : Symbol(Enum, Decl(merge.ts, 4, 8)) + +=== tests/cases/conformance/constEnums/index.ts === +import { Enum } from "./merge"; +>Enum : Symbol(Enum, Decl(index.ts, 0, 8)) + +Enum.One; +>Enum.One : Symbol(Enum.One, Decl(enum.ts, 0, 24)) +>Enum : Symbol(Enum, Decl(index.ts, 0, 8)) +>One : Symbol(Enum.One, Decl(enum.ts, 0, 24)) + diff --git a/tests/baselines/reference/importElisionConstEnumMerge1.types b/tests/baselines/reference/importElisionConstEnumMerge1.types new file mode 100644 index 0000000000000..6348e869642f3 --- /dev/null +++ b/tests/baselines/reference/importElisionConstEnumMerge1.types @@ -0,0 +1,29 @@ +=== tests/cases/conformance/constEnums/enum.ts === +export const enum Enum { +>Enum : Enum + + One = 1, +>One : Enum.One +>1 : 1 +} + +=== tests/cases/conformance/constEnums/merge.ts === +import { Enum } from "./enum"; +>Enum : typeof Enum + +namespace Enum { + export type Foo = number; +>Foo : number +} +export { Enum }; +>Enum : typeof Enum + +=== tests/cases/conformance/constEnums/index.ts === +import { Enum } from "./merge"; +>Enum : typeof import("tests/cases/conformance/constEnums/enum").Enum + +Enum.One; +>Enum.One : import("tests/cases/conformance/constEnums/enum").Enum +>Enum : typeof import("tests/cases/conformance/constEnums/enum").Enum +>One : import("tests/cases/conformance/constEnums/enum").Enum + diff --git a/tests/baselines/reference/jsDeclarationsImportAliasExposedWithinNamespace.types b/tests/baselines/reference/jsDeclarationsImportAliasExposedWithinNamespace.types index 28424f9792bc4..7c29ca32963cc 100644 --- a/tests/baselines/reference/jsDeclarationsImportAliasExposedWithinNamespace.types +++ b/tests/baselines/reference/jsDeclarationsImportAliasExposedWithinNamespace.types @@ -26,7 +26,7 @@ export {myTypes}; === tests/cases/conformance/jsdoc/declarations/file2.js === import {myTypes} from './file.js'; ->myTypes : any +>myTypes : { [x: string]: any; } /** * @namespace testFnTypes diff --git a/tests/baselines/reference/noCrashOnImportShadowing.errors.txt b/tests/baselines/reference/noCrashOnImportShadowing.errors.txt index ddd49c0c2c719..59fee7c6950d7 100644 --- a/tests/baselines/reference/noCrashOnImportShadowing.errors.txt +++ b/tests/baselines/reference/noCrashOnImportShadowing.errors.txt @@ -1,4 +1,3 @@ -tests/cases/compiler/index.ts(4,1): error TS2693: 'B' only refers to a type, but is being used as a value here. tests/cases/compiler/index.ts(9,10): error TS2709: Cannot use namespace 'OriginalB' as a type. @@ -17,13 +16,11 @@ tests/cases/compiler/index.ts(9,10): error TS2709: Cannot use namespace 'Origina export { B }; -==== tests/cases/compiler/index.ts (2 errors) ==== +==== tests/cases/compiler/index.ts (1 errors) ==== import { B } from "./a"; const x: B = { x: "" }; B.zzz; - ~ -!!! error TS2693: 'B' only refers to a type, but is being used as a value here. import * as OriginalB from "./b"; OriginalB.zzz; diff --git a/tests/baselines/reference/noCrashOnImportShadowing.js b/tests/baselines/reference/noCrashOnImportShadowing.js index 9c8ff2f8452f3..fe540d8585454 100644 --- a/tests/baselines/reference/noCrashOnImportShadowing.js +++ b/tests/baselines/reference/noCrashOnImportShadowing.js @@ -34,12 +34,15 @@ exports.zzz = 123; //// [a.js] "use strict"; exports.__esModule = true; +exports.B = void 0; var B = require("./b"); +exports.B = B; var x = { x: "" }; B.zzz; //// [index.js] "use strict"; exports.__esModule = true; +var a_1 = require("./a"); var x = { x: "" }; a_1.B.zzz; var OriginalB = require("./b"); diff --git a/tests/baselines/reference/noCrashOnImportShadowing.symbols b/tests/baselines/reference/noCrashOnImportShadowing.symbols index da5f5146ec27f..a9093debbb0f4 100644 --- a/tests/baselines/reference/noCrashOnImportShadowing.symbols +++ b/tests/baselines/reference/noCrashOnImportShadowing.symbols @@ -36,6 +36,9 @@ const x: B = { x: "" }; >x : Symbol(x, Decl(index.ts, 2, 14)) B.zzz; +>B.zzz : Symbol(OriginalB.zzz, Decl(b.ts, 0, 12)) +>B : Symbol(B, Decl(index.ts, 0, 8)) +>zzz : Symbol(OriginalB.zzz, Decl(b.ts, 0, 12)) import * as OriginalB from "./b"; >OriginalB : Symbol(OriginalB, Decl(index.ts, 5, 6)) diff --git a/tests/baselines/reference/noCrashOnImportShadowing.types b/tests/baselines/reference/noCrashOnImportShadowing.types index a4c75125716ec..3d4d58b20a126 100644 --- a/tests/baselines/reference/noCrashOnImportShadowing.types +++ b/tests/baselines/reference/noCrashOnImportShadowing.types @@ -24,11 +24,11 @@ B.zzz; >zzz : 123 export { B }; ->B : any +>B : typeof B === tests/cases/compiler/index.ts === import { B } from "./a"; ->B : any +>B : typeof OriginalB const x: B = { x: "" }; >x : B @@ -37,9 +37,9 @@ const x: B = { x: "" }; >"" : "" B.zzz; ->B.zzz : any ->B : any ->zzz : any +>B.zzz : 123 +>B : typeof OriginalB +>zzz : 123 import * as OriginalB from "./b"; >OriginalB : typeof OriginalB diff --git a/tests/baselines/reference/shadowedInternalModule.errors.txt b/tests/baselines/reference/shadowedInternalModule.errors.txt index f278ebcb6066e..eb33b7e12d3bd 100644 --- a/tests/baselines/reference/shadowedInternalModule.errors.txt +++ b/tests/baselines/reference/shadowedInternalModule.errors.txt @@ -1,8 +1,10 @@ tests/cases/conformance/internalModules/importDeclarations/shadowedInternalModule.ts(13,20): error TS2437: Module 'A' is hidden by a local declaration with the same name. tests/cases/conformance/internalModules/importDeclarations/shadowedInternalModule.ts(30,5): error TS2440: Import declaration conflicts with local declaration of 'Y'. +tests/cases/conformance/internalModules/importDeclarations/shadowedInternalModule.ts(47,10): error TS2438: Import name cannot be 'any'. +tests/cases/conformance/internalModules/importDeclarations/shadowedInternalModule.ts(62,3): error TS2440: Import declaration conflicts with local declaration of 'Q'. -==== tests/cases/conformance/internalModules/importDeclarations/shadowedInternalModule.ts (2 errors) ==== +==== tests/cases/conformance/internalModules/importDeclarations/shadowedInternalModule.ts (4 errors) ==== // all errors imported modules conflict with local variables module A { @@ -39,4 +41,40 @@ tests/cases/conformance/internalModules/importDeclarations/shadowedInternalModul !!! error TS2440: Import declaration conflicts with local declaration of 'Y'. var Y = 12; - } \ No newline at end of file + } + + // + + module a { + export type A = number; + } + + module b { + export import A = a.A; + export module A {} + } + + module c { + import any = b.A; + ~~~ +!!! error TS2438: Import name cannot be 'any'. + } + + // + + module q { + export const Q = {}; + } + + module r { + export import Q = q.Q; + export type Q = number; + } + + module s { + import Q = r.Q; + ~~~~~~~~~~~~~~~ +!!! error TS2440: Import declaration conflicts with local declaration of 'Q'. + const Q = 0; + } + \ No newline at end of file diff --git a/tests/baselines/reference/shadowedInternalModule.js b/tests/baselines/reference/shadowedInternalModule.js index 5d8e33d5eeb6c..63d2e6be2f5f5 100644 --- a/tests/baselines/reference/shadowedInternalModule.js +++ b/tests/baselines/reference/shadowedInternalModule.js @@ -31,7 +31,39 @@ module Z { import Y = X.Y; var Y = 12; -} +} + +// + +module a { + export type A = number; +} + +module b { + export import A = a.A; + export module A {} +} + +module c { + import any = b.A; +} + +// + +module q { + export const Q = {}; +} + +module r { + export import Q = q.Q; + export type Q = number; +} + +module s { + import Q = r.Q; + const Q = 0; +} + //// [shadowedInternalModule.js] // all errors imported modules conflict with local variables @@ -56,3 +88,19 @@ var Z; (function (Z) { var Y = 12; })(Z || (Z = {})); +var b; +(function (b) { +})(b || (b = {})); +// +var q; +(function (q) { + q.Q = {}; +})(q || (q = {})); +var r; +(function (r) { + r.Q = q.Q; +})(r || (r = {})); +var s; +(function (s) { + var Q = 0; +})(s || (s = {})); diff --git a/tests/baselines/reference/shadowedInternalModule.symbols b/tests/baselines/reference/shadowedInternalModule.symbols index b6293023cc877..02a12b4966679 100644 --- a/tests/baselines/reference/shadowedInternalModule.symbols +++ b/tests/baselines/reference/shadowedInternalModule.symbols @@ -69,3 +69,67 @@ module Z { var Y = 12; >Y : Symbol(Y, Decl(shadowedInternalModule.ts, 28, 10), Decl(shadowedInternalModule.ts, 31, 7)) } + +// + +module a { +>a : Symbol(a, Decl(shadowedInternalModule.ts, 32, 1)) + + export type A = number; +>A : Symbol(A, Decl(shadowedInternalModule.ts, 36, 10)) +} + +module b { +>b : Symbol(b, Decl(shadowedInternalModule.ts, 38, 1)) + + export import A = a.A; +>A : Symbol(A, Decl(shadowedInternalModule.ts, 40, 10), Decl(shadowedInternalModule.ts, 41, 24)) +>a : Symbol(a, Decl(shadowedInternalModule.ts, 32, 1)) +>A : Symbol(A, Decl(shadowedInternalModule.ts, 36, 10)) + + export module A {} +>A : Symbol(A, Decl(shadowedInternalModule.ts, 40, 10), Decl(shadowedInternalModule.ts, 41, 24)) +} + +module c { +>c : Symbol(c, Decl(shadowedInternalModule.ts, 43, 1)) + + import any = b.A; +>any : Symbol(any, Decl(shadowedInternalModule.ts, 45, 10)) +>b : Symbol(b, Decl(shadowedInternalModule.ts, 38, 1)) +>A : Symbol(any, Decl(shadowedInternalModule.ts, 40, 10), Decl(shadowedInternalModule.ts, 41, 24)) +} + +// + +module q { +>q : Symbol(q, Decl(shadowedInternalModule.ts, 47, 1)) + + export const Q = {}; +>Q : Symbol(Q, Decl(shadowedInternalModule.ts, 52, 14)) +} + +module r { +>r : Symbol(r, Decl(shadowedInternalModule.ts, 53, 1)) + + export import Q = q.Q; +>Q : Symbol(Q, Decl(shadowedInternalModule.ts, 55, 10), Decl(shadowedInternalModule.ts, 56, 24)) +>q : Symbol(q, Decl(shadowedInternalModule.ts, 47, 1)) +>Q : Symbol(Q, Decl(shadowedInternalModule.ts, 52, 14)) + + export type Q = number; +>Q : Symbol(Q, Decl(shadowedInternalModule.ts, 55, 10), Decl(shadowedInternalModule.ts, 56, 24)) +} + +module s { +>s : Symbol(s, Decl(shadowedInternalModule.ts, 58, 1)) + + import Q = r.Q; +>Q : Symbol(Q, Decl(shadowedInternalModule.ts, 60, 10), Decl(shadowedInternalModule.ts, 62, 7)) +>r : Symbol(r, Decl(shadowedInternalModule.ts, 53, 1)) +>Q : Symbol(Q, Decl(shadowedInternalModule.ts, 55, 10), Decl(shadowedInternalModule.ts, 56, 24)) + + const Q = 0; +>Q : Symbol(Q, Decl(shadowedInternalModule.ts, 60, 10), Decl(shadowedInternalModule.ts, 62, 7)) +} + diff --git a/tests/baselines/reference/shadowedInternalModule.types b/tests/baselines/reference/shadowedInternalModule.types index f3e7ee5e81451..5c52bf84a810a 100644 --- a/tests/baselines/reference/shadowedInternalModule.types +++ b/tests/baselines/reference/shadowedInternalModule.types @@ -70,3 +70,64 @@ module Z { >Y : number >12 : 12 } + +// + +module a { + export type A = number; +>A : number +} + +module b { +>b : typeof b + + export import A = a.A; +>A : any +>a : any +>A : number + + export module A {} +} + +module c { + import any = b.A; +>any : any +>b : typeof b +>A : number +} + +// + +module q { +>q : typeof q + + export const Q = {}; +>Q : {} +>{} : {} +} + +module r { +>r : typeof r + + export import Q = q.Q; +>Q : {} +>q : typeof q +>Q : {} + + export type Q = number; +>Q : number +} + +module s { +>s : typeof s + + import Q = r.Q; +>Q : 0 +>r : typeof r +>Q : number + + const Q = 0; +>Q : 0 +>0 : 0 +} + diff --git a/tests/baselines/reference/typeAndNamespaceExportMerge.js b/tests/baselines/reference/typeAndNamespaceExportMerge.js new file mode 100644 index 0000000000000..8c939fca7d582 --- /dev/null +++ b/tests/baselines/reference/typeAndNamespaceExportMerge.js @@ -0,0 +1,38 @@ +//// [tests/cases/conformance/externalModules/typeAndNamespaceExportMerge.ts] //// + +//// [constants.ts] +// @strict + +export const COFFEE = 0; +export const TEA = 1; + + +//// [drink.ts] +export type Drink = 0 | 1; +export * as Drink from "./constants"; + + +//// [index.ts] +import { Drink } from "./drink"; +// 'Drink' only refers to a type, but is being used as a value here +const x: Drink = Drink.TEA; + + +//// [constants.js] +"use strict"; +// @strict +exports.__esModule = true; +exports.TEA = exports.COFFEE = void 0; +exports.COFFEE = 0; +exports.TEA = 1; +//// [drink.js] +"use strict"; +exports.__esModule = true; +exports.Drink = void 0; +exports.Drink = require("./constants"); +//// [index.js] +"use strict"; +exports.__esModule = true; +var drink_1 = require("./drink"); +// 'Drink' only refers to a type, but is being used as a value here +var x = drink_1.Drink.TEA; diff --git a/tests/baselines/reference/typeAndNamespaceExportMerge.symbols b/tests/baselines/reference/typeAndNamespaceExportMerge.symbols new file mode 100644 index 0000000000000..77cbe73f5cae7 --- /dev/null +++ b/tests/baselines/reference/typeAndNamespaceExportMerge.symbols @@ -0,0 +1,30 @@ +=== tests/cases/conformance/externalModules/constants.ts === +// @strict + +export const COFFEE = 0; +>COFFEE : Symbol(COFFEE, Decl(constants.ts, 2, 12)) + +export const TEA = 1; +>TEA : Symbol(TEA, Decl(constants.ts, 3, 12)) + + +=== tests/cases/conformance/externalModules/drink.ts === +export type Drink = 0 | 1; +>Drink : Symbol(Drink, Decl(drink.ts, 0, 0), Decl(drink.ts, 1, 6)) + +export * as Drink from "./constants"; +>Drink : Symbol(Drink, Decl(drink.ts, 0, 0), Decl(drink.ts, 1, 6)) + + +=== tests/cases/conformance/externalModules/index.ts === +import { Drink } from "./drink"; +>Drink : Symbol(Drink, Decl(index.ts, 0, 8)) + +// 'Drink' only refers to a type, but is being used as a value here +const x: Drink = Drink.TEA; +>x : Symbol(x, Decl(index.ts, 2, 5)) +>Drink : Symbol(Drink, Decl(index.ts, 0, 8)) +>Drink.TEA : Symbol(TEA, Decl(constants.ts, 3, 12)) +>Drink : Symbol(Drink, Decl(index.ts, 0, 8)) +>TEA : Symbol(TEA, Decl(constants.ts, 3, 12)) + diff --git a/tests/baselines/reference/typeAndNamespaceExportMerge.types b/tests/baselines/reference/typeAndNamespaceExportMerge.types new file mode 100644 index 0000000000000..86a89b6c4a4c1 --- /dev/null +++ b/tests/baselines/reference/typeAndNamespaceExportMerge.types @@ -0,0 +1,31 @@ +=== tests/cases/conformance/externalModules/constants.ts === +// @strict + +export const COFFEE = 0; +>COFFEE : 0 +>0 : 0 + +export const TEA = 1; +>TEA : 1 +>1 : 1 + + +=== tests/cases/conformance/externalModules/drink.ts === +export type Drink = 0 | 1; +>Drink : 0 | 1 + +export * as Drink from "./constants"; +>Drink : typeof import("tests/cases/conformance/externalModules/constants") + + +=== tests/cases/conformance/externalModules/index.ts === +import { Drink } from "./drink"; +>Drink : typeof import("tests/cases/conformance/externalModules/constants") + +// 'Drink' only refers to a type, but is being used as a value here +const x: Drink = Drink.TEA; +>x : Drink +>Drink.TEA : 1 +>Drink : typeof import("tests/cases/conformance/externalModules/constants") +>TEA : 1 + diff --git a/tests/baselines/reference/typeOnlyMerge1.js b/tests/baselines/reference/typeOnlyMerge1.js new file mode 100644 index 0000000000000..0def9774590d2 --- /dev/null +++ b/tests/baselines/reference/typeOnlyMerge1.js @@ -0,0 +1,30 @@ +//// [tests/cases/conformance/externalModules/typeOnlyMerge1.ts] //// + +//// [a.ts] +interface A {} +export type { A }; + +//// [b.ts] +import { A } from "./a"; +const A = 0; +export { A }; + +//// [c.ts] +import { A } from "./b"; +A; + + +//// [a.js] +"use strict"; +exports.__esModule = true; +//// [b.js] +"use strict"; +exports.__esModule = true; +exports.A = void 0; +var A = 0; +exports.A = A; +//// [c.js] +"use strict"; +exports.__esModule = true; +var b_1 = require("./b"); +b_1.A; diff --git a/tests/baselines/reference/typeOnlyMerge1.symbols b/tests/baselines/reference/typeOnlyMerge1.symbols new file mode 100644 index 0000000000000..f00f855f24f6e --- /dev/null +++ b/tests/baselines/reference/typeOnlyMerge1.symbols @@ -0,0 +1,24 @@ +=== tests/cases/conformance/externalModules/a.ts === +interface A {} +>A : Symbol(A, Decl(a.ts, 0, 0)) + +export type { A }; +>A : Symbol(A, Decl(a.ts, 1, 13)) + +=== tests/cases/conformance/externalModules/b.ts === +import { A } from "./a"; +>A : Symbol(A, Decl(b.ts, 0, 8), Decl(b.ts, 1, 5)) + +const A = 0; +>A : Symbol(A, Decl(b.ts, 0, 8), Decl(b.ts, 1, 5)) + +export { A }; +>A : Symbol(A, Decl(b.ts, 2, 8)) + +=== tests/cases/conformance/externalModules/c.ts === +import { A } from "./b"; +>A : Symbol(A, Decl(c.ts, 0, 8)) + +A; +>A : Symbol(A, Decl(c.ts, 0, 8)) + diff --git a/tests/baselines/reference/typeOnlyMerge1.types b/tests/baselines/reference/typeOnlyMerge1.types new file mode 100644 index 0000000000000..bd7c9f0d4f5df --- /dev/null +++ b/tests/baselines/reference/typeOnlyMerge1.types @@ -0,0 +1,23 @@ +=== tests/cases/conformance/externalModules/a.ts === +interface A {} +export type { A }; +>A : A + +=== tests/cases/conformance/externalModules/b.ts === +import { A } from "./a"; +>A : 0 + +const A = 0; +>A : 0 +>0 : 0 + +export { A }; +>A : 0 + +=== tests/cases/conformance/externalModules/c.ts === +import { A } from "./b"; +>A : 0 + +A; +>A : 0 + diff --git a/tests/baselines/reference/typeOnlyMerge2.errors.txt b/tests/baselines/reference/typeOnlyMerge2.errors.txt new file mode 100644 index 0000000000000..de777c96d996b --- /dev/null +++ b/tests/baselines/reference/typeOnlyMerge2.errors.txt @@ -0,0 +1,24 @@ +tests/cases/conformance/externalModules/d.ts(2,1): error TS1362: 'A' cannot be used as a value because it was exported using 'export type'. + + +==== tests/cases/conformance/externalModules/a.ts (0 errors) ==== + const A = {} + export { A }; + +==== tests/cases/conformance/externalModules/b.ts (0 errors) ==== + import { A } from "./a"; + type A = any; + export type { A }; + +==== tests/cases/conformance/externalModules/c.ts (0 errors) ==== + import { A } from "./b"; + namespace A {} + export { A }; + +==== tests/cases/conformance/externalModules/d.ts (1 errors) ==== + import { A } from "./c"; + A; + ~ +!!! error TS1362: 'A' cannot be used as a value because it was exported using 'export type'. +!!! related TS1377 tests/cases/conformance/externalModules/b.ts:3:15: 'A' was exported here. + \ No newline at end of file diff --git a/tests/baselines/reference/typeOnlyMerge2.js b/tests/baselines/reference/typeOnlyMerge2.js new file mode 100644 index 0000000000000..39930739f7094 --- /dev/null +++ b/tests/baselines/reference/typeOnlyMerge2.js @@ -0,0 +1,37 @@ +//// [tests/cases/conformance/externalModules/typeOnlyMerge2.ts] //// + +//// [a.ts] +const A = {} +export { A }; + +//// [b.ts] +import { A } from "./a"; +type A = any; +export type { A }; + +//// [c.ts] +import { A } from "./b"; +namespace A {} +export { A }; + +//// [d.ts] +import { A } from "./c"; +A; + + +//// [a.js] +"use strict"; +exports.__esModule = true; +exports.A = void 0; +var A = {}; +exports.A = A; +//// [b.js] +"use strict"; +exports.__esModule = true; +//// [c.js] +"use strict"; +exports.__esModule = true; +//// [d.js] +"use strict"; +exports.__esModule = true; +A; diff --git a/tests/baselines/reference/typeOnlyMerge2.symbols b/tests/baselines/reference/typeOnlyMerge2.symbols new file mode 100644 index 0000000000000..48c1a7d8cec80 --- /dev/null +++ b/tests/baselines/reference/typeOnlyMerge2.symbols @@ -0,0 +1,34 @@ +=== tests/cases/conformance/externalModules/a.ts === +const A = {} +>A : Symbol(A, Decl(a.ts, 0, 5)) + +export { A }; +>A : Symbol(A, Decl(a.ts, 1, 8)) + +=== tests/cases/conformance/externalModules/b.ts === +import { A } from "./a"; +>A : Symbol(A, Decl(b.ts, 0, 8), Decl(b.ts, 0, 24)) + +type A = any; +>A : Symbol(A, Decl(b.ts, 0, 8), Decl(b.ts, 0, 24)) + +export type { A }; +>A : Symbol(A, Decl(b.ts, 2, 13)) + +=== tests/cases/conformance/externalModules/c.ts === +import { A } from "./b"; +>A : Symbol(A, Decl(c.ts, 0, 8), Decl(c.ts, 0, 24)) + +namespace A {} +>A : Symbol(A, Decl(c.ts, 0, 8), Decl(c.ts, 0, 24)) + +export { A }; +>A : Symbol(A, Decl(c.ts, 2, 8)) + +=== tests/cases/conformance/externalModules/d.ts === +import { A } from "./c"; +>A : Symbol(A, Decl(d.ts, 0, 8)) + +A; +>A : Symbol(A, Decl(d.ts, 0, 8)) + diff --git a/tests/baselines/reference/typeOnlyMerge2.types b/tests/baselines/reference/typeOnlyMerge2.types new file mode 100644 index 0000000000000..7200dd36c1bfe --- /dev/null +++ b/tests/baselines/reference/typeOnlyMerge2.types @@ -0,0 +1,33 @@ +=== tests/cases/conformance/externalModules/a.ts === +const A = {} +>A : {} +>{} : {} + +export { A }; +>A : {} + +=== tests/cases/conformance/externalModules/b.ts === +import { A } from "./a"; +>A : {} + +type A = any; +>A : any + +export type { A }; +>A : any + +=== tests/cases/conformance/externalModules/c.ts === +import { A } from "./b"; +>A : {} + +namespace A {} +export { A }; +>A : {} + +=== tests/cases/conformance/externalModules/d.ts === +import { A } from "./c"; +>A : {} + +A; +>A : {} + diff --git a/tests/baselines/reference/typeOnlyMerge3.errors.txt b/tests/baselines/reference/typeOnlyMerge3.errors.txt new file mode 100644 index 0000000000000..84a31d71065ad --- /dev/null +++ b/tests/baselines/reference/typeOnlyMerge3.errors.txt @@ -0,0 +1,39 @@ +tests/cases/conformance/externalModules/b.ts(1,10): error TS2440: Import declaration conflicts with local declaration of 'A'. +tests/cases/conformance/externalModules/c.ts(2,1): error TS1362: 'A' cannot be used as a value because it was exported using 'export type'. +tests/cases/conformance/externalModules/c.ts(3,1): error TS1362: 'A' cannot be used as a value because it was exported using 'export type'. +tests/cases/conformance/externalModules/c.ts(4,1): error TS1362: 'A' cannot be used as a value because it was exported using 'export type'. +tests/cases/conformance/externalModules/c.ts(4,1): error TS2349: This expression is not callable. + Type 'typeof A' has no call signatures. + + +==== tests/cases/conformance/externalModules/a.ts (0 errors) ==== + function A() {} + export type { A }; + +==== tests/cases/conformance/externalModules/b.ts (1 errors) ==== + import { A } from "./a"; + ~ +!!! error TS2440: Import declaration conflicts with local declaration of 'A'. + namespace A { + export const displayName = "A"; + } + export { A }; + +==== tests/cases/conformance/externalModules/c.ts (4 errors) ==== + import { A } from "./b"; + A; + ~ +!!! error TS1362: 'A' cannot be used as a value because it was exported using 'export type'. +!!! related TS1377 tests/cases/conformance/externalModules/a.ts:2:15: 'A' was exported here. + A.displayName; + ~ +!!! error TS1362: 'A' cannot be used as a value because it was exported using 'export type'. +!!! related TS1377 tests/cases/conformance/externalModules/a.ts:2:15: 'A' was exported here. + A(); + ~ +!!! error TS1362: 'A' cannot be used as a value because it was exported using 'export type'. +!!! related TS1377 tests/cases/conformance/externalModules/a.ts:2:15: 'A' was exported here. + ~ +!!! error TS2349: This expression is not callable. +!!! error TS2349: Type 'typeof A' has no call signatures. + \ No newline at end of file diff --git a/tests/baselines/reference/typeOnlyMerge3.js b/tests/baselines/reference/typeOnlyMerge3.js new file mode 100644 index 0000000000000..d3afde76abd6f --- /dev/null +++ b/tests/baselines/reference/typeOnlyMerge3.js @@ -0,0 +1,37 @@ +//// [tests/cases/conformance/externalModules/typeOnlyMerge3.ts] //// + +//// [a.ts] +function A() {} +export type { A }; + +//// [b.ts] +import { A } from "./a"; +namespace A { + export const displayName = "A"; +} +export { A }; + +//// [c.ts] +import { A } from "./b"; +A; +A.displayName; +A(); + + +//// [a.js] +"use strict"; +exports.__esModule = true; +function A() { } +//// [b.js] +"use strict"; +exports.__esModule = true; +var A; +(function (A) { + A.displayName = "A"; +})(A || (A = {})); +//// [c.js] +"use strict"; +exports.__esModule = true; +A; +A.displayName; +A(); diff --git a/tests/baselines/reference/typeOnlyMerge3.symbols b/tests/baselines/reference/typeOnlyMerge3.symbols new file mode 100644 index 0000000000000..12ce75f56da55 --- /dev/null +++ b/tests/baselines/reference/typeOnlyMerge3.symbols @@ -0,0 +1,35 @@ +=== tests/cases/conformance/externalModules/a.ts === +function A() {} +>A : Symbol(A, Decl(a.ts, 0, 0)) + +export type { A }; +>A : Symbol(A, Decl(a.ts, 1, 13)) + +=== tests/cases/conformance/externalModules/b.ts === +import { A } from "./a"; +>A : Symbol(A, Decl(b.ts, 0, 8), Decl(b.ts, 0, 24)) + +namespace A { +>A : Symbol(A, Decl(b.ts, 0, 8), Decl(b.ts, 0, 24)) + + export const displayName = "A"; +>displayName : Symbol(displayName, Decl(b.ts, 2, 14)) +} +export { A }; +>A : Symbol(A, Decl(b.ts, 4, 8)) + +=== tests/cases/conformance/externalModules/c.ts === +import { A } from "./b"; +>A : Symbol(A, Decl(c.ts, 0, 8)) + +A; +>A : Symbol(A, Decl(c.ts, 0, 8)) + +A.displayName; +>A.displayName : Symbol(A.displayName, Decl(b.ts, 2, 14)) +>A : Symbol(A, Decl(c.ts, 0, 8)) +>displayName : Symbol(A.displayName, Decl(b.ts, 2, 14)) + +A(); +>A : Symbol(A, Decl(c.ts, 0, 8)) + diff --git a/tests/baselines/reference/typeOnlyMerge3.types b/tests/baselines/reference/typeOnlyMerge3.types new file mode 100644 index 0000000000000..b2a860c61abb5 --- /dev/null +++ b/tests/baselines/reference/typeOnlyMerge3.types @@ -0,0 +1,37 @@ +=== tests/cases/conformance/externalModules/a.ts === +function A() {} +>A : () => void + +export type { A }; +>A : any + +=== tests/cases/conformance/externalModules/b.ts === +import { A } from "./a"; +>A : typeof A + +namespace A { +>A : typeof A + + export const displayName = "A"; +>displayName : "A" +>"A" : "A" +} +export { A }; +>A : typeof A + +=== tests/cases/conformance/externalModules/c.ts === +import { A } from "./b"; +>A : typeof A + +A; +>A : typeof A + +A.displayName; +>A.displayName : "A" +>A : typeof A +>displayName : "A" + +A(); +>A() : any +>A : typeof A + diff --git a/tests/baselines/reference/valuesMergingAcrossModules.errors.txt b/tests/baselines/reference/valuesMergingAcrossModules.errors.txt new file mode 100644 index 0000000000000..de88fe9c53b05 --- /dev/null +++ b/tests/baselines/reference/valuesMergingAcrossModules.errors.txt @@ -0,0 +1,28 @@ +tests/cases/conformance/externalModules/c.ts(1,10): error TS2440: Import declaration conflicts with local declaration of 'A'. +tests/cases/conformance/externalModules/c.ts(6,1): error TS2349: This expression is not callable. + Type 'typeof A' has no call signatures. + + +==== tests/cases/conformance/externalModules/a.ts (0 errors) ==== + function A() {} + export { A }; + +==== tests/cases/conformance/externalModules/b.ts (0 errors) ==== + import { A } from "./a"; + type A = 0; + export { A }; + +==== tests/cases/conformance/externalModules/c.ts (2 errors) ==== + import { A } from "./b"; + ~ +!!! error TS2440: Import declaration conflicts with local declaration of 'A'. + namespace A { + export const displayName = "A"; + } + + A(); + ~ +!!! error TS2349: This expression is not callable. +!!! error TS2349: Type 'typeof A' has no call signatures. + A.displayName; + \ No newline at end of file diff --git a/tests/baselines/reference/valuesMergingAcrossModules.js b/tests/baselines/reference/valuesMergingAcrossModules.js new file mode 100644 index 0000000000000..b8b3c0a0a5c84 --- /dev/null +++ b/tests/baselines/reference/valuesMergingAcrossModules.js @@ -0,0 +1,42 @@ +//// [tests/cases/conformance/externalModules/valuesMergingAcrossModules.ts] //// + +//// [a.ts] +function A() {} +export { A }; + +//// [b.ts] +import { A } from "./a"; +type A = 0; +export { A }; + +//// [c.ts] +import { A } from "./b"; +namespace A { + export const displayName = "A"; +} + +A(); +A.displayName; + + +//// [a.js] +"use strict"; +exports.__esModule = true; +exports.A = void 0; +function A() { } +exports.A = A; +//// [b.js] +"use strict"; +exports.__esModule = true; +exports.A = void 0; +var a_1 = require("./a"); +exports.A = a_1.A; +//// [c.js] +"use strict"; +exports.__esModule = true; +var A; +(function (A) { + A.displayName = "A"; +})(A || (A = {})); +A(); +A.displayName; diff --git a/tests/baselines/reference/valuesMergingAcrossModules.symbols b/tests/baselines/reference/valuesMergingAcrossModules.symbols new file mode 100644 index 0000000000000..fd854e4cbd42a --- /dev/null +++ b/tests/baselines/reference/valuesMergingAcrossModules.symbols @@ -0,0 +1,36 @@ +=== tests/cases/conformance/externalModules/a.ts === +function A() {} +>A : Symbol(A, Decl(a.ts, 0, 0)) + +export { A }; +>A : Symbol(A, Decl(a.ts, 1, 8)) + +=== tests/cases/conformance/externalModules/b.ts === +import { A } from "./a"; +>A : Symbol(A, Decl(b.ts, 0, 8), Decl(b.ts, 0, 24)) + +type A = 0; +>A : Symbol(A, Decl(b.ts, 0, 8), Decl(b.ts, 0, 24)) + +export { A }; +>A : Symbol(A, Decl(b.ts, 2, 8)) + +=== tests/cases/conformance/externalModules/c.ts === +import { A } from "./b"; +>A : Symbol(A, Decl(c.ts, 0, 8), Decl(c.ts, 0, 24)) + +namespace A { +>A : Symbol(A, Decl(c.ts, 0, 8), Decl(c.ts, 0, 24)) + + export const displayName = "A"; +>displayName : Symbol(displayName, Decl(c.ts, 2, 14)) +} + +A(); +>A : Symbol(A, Decl(c.ts, 0, 8), Decl(c.ts, 0, 24)) + +A.displayName; +>A.displayName : Symbol(A.displayName, Decl(c.ts, 2, 14)) +>A : Symbol(A, Decl(c.ts, 0, 8), Decl(c.ts, 0, 24)) +>displayName : Symbol(A.displayName, Decl(c.ts, 2, 14)) + diff --git a/tests/baselines/reference/valuesMergingAcrossModules.types b/tests/baselines/reference/valuesMergingAcrossModules.types new file mode 100644 index 0000000000000..9e47dd9945bea --- /dev/null +++ b/tests/baselines/reference/valuesMergingAcrossModules.types @@ -0,0 +1,38 @@ +=== tests/cases/conformance/externalModules/a.ts === +function A() {} +>A : () => void + +export { A }; +>A : () => void + +=== tests/cases/conformance/externalModules/b.ts === +import { A } from "./a"; +>A : () => void + +type A = 0; +>A : 0 + +export { A }; +>A : () => void + +=== tests/cases/conformance/externalModules/c.ts === +import { A } from "./b"; +>A : typeof A + +namespace A { +>A : typeof A + + export const displayName = "A"; +>displayName : "A" +>"A" : "A" +} + +A(); +>A() : any +>A : typeof A + +A.displayName; +>A.displayName : "A" +>A : typeof A +>displayName : "A" + diff --git a/tests/cases/conformance/constEnums/importElisionConstEnumMerge1.ts b/tests/cases/conformance/constEnums/importElisionConstEnumMerge1.ts new file mode 100644 index 0000000000000..9884a7615a362 --- /dev/null +++ b/tests/cases/conformance/constEnums/importElisionConstEnumMerge1.ts @@ -0,0 +1,15 @@ +// @Filename: enum.ts +export const enum Enum { + One = 1, +} + +// @Filename: merge.ts +import { Enum } from "./enum"; +namespace Enum { + export type Foo = number; +} +export { Enum }; + +// @Filename: index.ts +import { Enum } from "./merge"; +Enum.One; diff --git a/tests/cases/conformance/externalModules/typeAndNamespaceExportMerge.ts b/tests/cases/conformance/externalModules/typeAndNamespaceExportMerge.ts new file mode 100644 index 0000000000000..a7a7d3f3e5698 --- /dev/null +++ b/tests/cases/conformance/externalModules/typeAndNamespaceExportMerge.ts @@ -0,0 +1,16 @@ +// @strict + +// @Filename: constants.ts +export const COFFEE = 0; +export const TEA = 1; + + +// @Filename: drink.ts +export type Drink = 0 | 1; +export * as Drink from "./constants"; + + +// @Filename: index.ts +import { Drink } from "./drink"; +// 'Drink' only refers to a type, but is being used as a value here +const x: Drink = Drink.TEA; diff --git a/tests/cases/conformance/externalModules/typeOnlyMerge1.ts b/tests/cases/conformance/externalModules/typeOnlyMerge1.ts new file mode 100644 index 0000000000000..59e77388deb48 --- /dev/null +++ b/tests/cases/conformance/externalModules/typeOnlyMerge1.ts @@ -0,0 +1,12 @@ +// @Filename: a.ts +interface A {} +export type { A }; + +// @Filename: b.ts +import { A } from "./a"; +const A = 0; +export { A }; + +// @Filename: c.ts +import { A } from "./b"; +A; diff --git a/tests/cases/conformance/externalModules/typeOnlyMerge2.ts b/tests/cases/conformance/externalModules/typeOnlyMerge2.ts new file mode 100644 index 0000000000000..54d69f7d2c3ad --- /dev/null +++ b/tests/cases/conformance/externalModules/typeOnlyMerge2.ts @@ -0,0 +1,17 @@ +// @Filename: a.ts +const A = {} +export { A }; + +// @Filename: b.ts +import { A } from "./a"; +type A = any; +export type { A }; + +// @Filename: c.ts +import { A } from "./b"; +namespace A {} +export { A }; + +// @Filename: d.ts +import { A } from "./c"; +A; diff --git a/tests/cases/conformance/externalModules/typeOnlyMerge3.ts b/tests/cases/conformance/externalModules/typeOnlyMerge3.ts new file mode 100644 index 0000000000000..d5085b05d86bf --- /dev/null +++ b/tests/cases/conformance/externalModules/typeOnlyMerge3.ts @@ -0,0 +1,16 @@ +// @Filename: a.ts +function A() {} +export type { A }; + +// @Filename: b.ts +import { A } from "./a"; +namespace A { + export const displayName = "A"; +} +export { A }; + +// @Filename: c.ts +import { A } from "./b"; +A; +A.displayName; +A(); diff --git a/tests/cases/conformance/externalModules/valuesMergingAcrossModules.ts b/tests/cases/conformance/externalModules/valuesMergingAcrossModules.ts new file mode 100644 index 0000000000000..00ae4f8fa63e6 --- /dev/null +++ b/tests/cases/conformance/externalModules/valuesMergingAcrossModules.ts @@ -0,0 +1,17 @@ +// @Filename: a.ts +function A() {} +export { A }; + +// @Filename: b.ts +import { A } from "./a"; +type A = 0; +export { A }; + +// @Filename: c.ts +import { A } from "./b"; +namespace A { + export const displayName = "A"; +} + +A(); +A.displayName; diff --git a/tests/cases/conformance/internalModules/importDeclarations/shadowedInternalModule.ts b/tests/cases/conformance/internalModules/importDeclarations/shadowedInternalModule.ts index dcdcdbd1eb61c..a2c9738455bb5 100644 --- a/tests/cases/conformance/internalModules/importDeclarations/shadowedInternalModule.ts +++ b/tests/cases/conformance/internalModules/importDeclarations/shadowedInternalModule.ts @@ -30,4 +30,35 @@ module Z { import Y = X.Y; var Y = 12; -} \ No newline at end of file +} + +// + +module a { + export type A = number; +} + +module b { + export import A = a.A; + export module A {} +} + +module c { + import any = b.A; +} + +// + +module q { + export const Q = {}; +} + +module r { + export import Q = q.Q; + export type Q = number; +} + +module s { + import Q = r.Q; + const Q = 0; +}