diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 4ffc5dc978b9a..007126c5c77ce 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2705,7 +2705,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return symbol; } if (symbol.flags & SymbolFlags.Alias) { - const targetFlags = getAllSymbolFlags(symbol); + const targetFlags = getSymbolFlags(symbol); // `targetFlags` will be `SymbolFlags.All` if an error occurred in alias resolution; this avoids cascading errors if (targetFlags & meaning) { return symbol; @@ -3724,7 +3724,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return true; } const symbol = resolveSymbol(resolveName(errorLocation, name, SymbolFlags.Type & ~SymbolFlags.Value, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ false)); - const allFlags = symbol && getAllSymbolFlags(symbol); + const allFlags = symbol && getSymbolFlags(symbol); if (symbol && allFlags !== undefined && !(allFlags & SymbolFlags.Value)) { const rawName = unescapeLeadingUnderscores(name); if (isES2015OrLaterConstructorName(name)) { @@ -4457,32 +4457,44 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { * @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; + function getSymbolFlags(symbol: Symbol, excludeTypeOnlyMeanings?: boolean, excludeLocalMeanings?: boolean): SymbolFlags { + const typeOnlyDeclaration = excludeTypeOnlyMeanings && getTypeOnlyAliasDeclaration(symbol); + const typeOnlyDeclarationIsExportStar = typeOnlyDeclaration && isExportDeclaration(typeOnlyDeclaration); + const typeOnlyResolution = typeOnlyDeclaration && ( + typeOnlyDeclarationIsExportStar + ? resolveExternalModuleName(typeOnlyDeclaration.moduleSpecifier, typeOnlyDeclaration.moduleSpecifier, /*ignoreErrors*/ true) + : resolveAlias(typeOnlyDeclaration.symbol)); + const typeOnlyExportStarTargets = typeOnlyDeclarationIsExportStar && typeOnlyResolution ? getExportsOfModule(typeOnlyResolution) : undefined; + let flags = excludeLocalMeanings ? SymbolFlags.None : symbol.flags; + let seenSymbols; + while (symbol.flags & SymbolFlags.Alias) { + const target = getExportSymbolOfValueSymbolIfExported(resolveAlias(symbol)); + if (!typeOnlyDeclarationIsExportStar && target === typeOnlyResolution || + typeOnlyExportStarTargets?.get(target.escapedName) === target + ) { + break; + } + 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; } /** @@ -4510,7 +4522,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { immediateTarget: Symbol | undefined, finalTarget: Symbol | undefined, overwriteEmpty: boolean, - exportStarDeclaration?: ExportDeclaration & { readonly isTypeOnly: true }, + exportStarDeclaration?: ExportDeclaration & { readonly isTypeOnly: true, readonly moduleSpecifier: Expression }, exportStarName?: __String, ): boolean { if (!aliasDeclaration || isPropertyAccessExpression(aliasDeclaration)) return false; @@ -4559,7 +4571,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const resolved = links.typeOnlyDeclaration.kind === SyntaxKind.ExportDeclaration ? resolveSymbol(getExportsOfModule(links.typeOnlyDeclaration.symbol.parent!).get(links.typeOnlyExportStarName || symbol.escapedName))! : resolveAlias(links.typeOnlyDeclaration.symbol); - return getAllSymbolFlags(resolved) & include ? links.typeOnlyDeclaration : undefined; + return getSymbolFlags(resolved) & include ? links.typeOnlyDeclaration : undefined; } return undefined; } @@ -4572,7 +4584,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const target = resolveAlias(symbol); if (target) { const markAlias = target === unknownSymbol || - ((getAllSymbolFlags(target) & SymbolFlags.Value) && !isConstEnumOrConstEnumOnlyModule(target) && !getTypeOnlyAliasDeclaration(symbol, SymbolFlags.Value)); + ((getSymbolFlags(symbol, /*excludeTypeOnlyMeanings*/ true) & SymbolFlags.Value) && !isConstEnumOrConstEnumOnlyModule(target)); if (markAlias) { markAliasSymbolAsReferenced(symbol); @@ -4594,7 +4606,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // This way a chain of imports can be elided if ultimately the final input is only used in a type // position. if (isInternalModuleImportEqualsDeclaration(node)) { - if (getAllSymbolFlags(resolveSymbol(symbol)) & SymbolFlags.Value) { + if (getSymbolFlags(resolveSymbol(symbol)) & SymbolFlags.Value) { // import foo = checkExpressionCached(node.moduleReference as Expression); } @@ -5309,7 +5321,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function getExportsOfModuleWorker(moduleSymbol: Symbol) { const visitedSymbols: Symbol[] = []; - let typeOnlyExportStarMap: Map<__String, ExportDeclaration & { readonly isTypeOnly: true }> | undefined; + let typeOnlyExportStarMap: Map<__String, ExportDeclaration & { readonly isTypeOnly: true, readonly moduleSpecifier: Expression }> | undefined; const nonTypeOnlyNames = new Set<__String>(); // A module defined by an 'export=' consists of one export that needs to be resolved @@ -5376,7 +5388,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { typeOnlyExportStarMap ??= new Map(); symbols.forEach((_, escapedName) => typeOnlyExportStarMap!.set( escapedName, - exportStar as ExportDeclaration & { readonly isTypeOnly: true })); + exportStar as ExportDeclaration & { readonly isTypeOnly: true, readonly moduleSpecifier: Expression })); } return symbols; } @@ -5567,7 +5579,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function symbolIsValue(symbol: Symbol, includeTypeOnlyMembers?: boolean): boolean { return !!( symbol.flags & SymbolFlags.Value || - symbol.flags & SymbolFlags.Alias && getAllSymbolFlags(symbol) & SymbolFlags.Value && (includeTypeOnlyMembers || !getTypeOnlyAliasDeclaration(symbol))); + symbol.flags & SymbolFlags.Alias && getSymbolFlags(symbol, !includeTypeOnlyMembers) & SymbolFlags.Value); } function findConstructorDeclaration(node: ClassLikeDeclaration): ConstructorDeclaration | undefined { @@ -5866,7 +5878,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Qualify if the symbol from symbol table has same meaning as expected const shouldResolveAlias = (symbolFromSymbolTable.flags & SymbolFlags.Alias && !getDeclarationOfKind(symbolFromSymbolTable, SyntaxKind.ExportSpecifier)); symbolFromSymbolTable = shouldResolveAlias ? resolveAlias(symbolFromSymbolTable) : symbolFromSymbolTable; - const flags = shouldResolveAlias ? getAllSymbolFlags(symbolFromSymbolTable) : symbolFromSymbolTable.flags; + const flags = shouldResolveAlias ? getSymbolFlags(symbolFromSymbolTable) : symbolFromSymbolTable.flags; if (flags & meaning) { qualify = true; return true; @@ -8905,7 +8917,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function isTypeOnlyNamespace(symbol: Symbol) { - return every(getNamespaceMembersForSerialization(symbol), m => !(getAllSymbolFlags(resolveSymbol(m)) & SymbolFlags.Value)); + return every(getNamespaceMembersForSerialization(symbol), m => !(getSymbolFlags(resolveSymbol(m)) & SymbolFlags.Value)); } function serializeModule(symbol: Symbol, symbolName: string, modifierFlags: ModifierFlags) { @@ -11416,7 +11428,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { links.type = exportSymbol?.declarations && isDuplicatedCommonJSExport(exportSymbol.declarations) && symbol.declarations!.length ? getFlowTypeFromCommonJSExport(exportSymbol) : isDuplicatedCommonJSExport(symbol.declarations) ? autoType : declaredType ? declaredType - : getAllSymbolFlags(targetSymbol) & SymbolFlags.Value ? getTypeOfSymbol(targetSymbol) + : getSymbolFlags(targetSymbol) & SymbolFlags.Value ? getTypeOfSymbol(targetSymbol) : errorType; } return links.type; @@ -27808,9 +27820,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!canCollectSymbolAliasAccessabilityData) { return; } - if (isNonLocalAlias(symbol, /*excludes*/ SymbolFlags.Value) && !isInTypeQuery(location) && !getTypeOnlyAliasDeclaration(symbol, SymbolFlags.Value)) { + if (isNonLocalAlias(symbol, /*excludes*/ SymbolFlags.Value) && !isInTypeQuery(location)) { const target = resolveAlias(symbol); - if (getAllSymbolFlags(target) & (SymbolFlags.Value | SymbolFlags.ExportValue)) { + if (getSymbolFlags(symbol, /*excludeTypeOnlyMeanings*/ true) & (SymbolFlags.Value | SymbolFlags.ExportValue)) { // 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. @@ -44235,7 +44247,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return; } - const targetFlags = getAllSymbolFlags(target); + const targetFlags = getSymbolFlags(target); const excludedMeanings = (symbol.flags & (SymbolFlags.Value | SymbolFlags.ExportValue) ? SymbolFlags.Value : 0) | (symbol.flags & SymbolFlags.Type ? SymbolFlags.Type : 0) | @@ -44437,7 +44449,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (node.moduleReference.kind !== SyntaxKind.ExternalModuleReference) { const target = resolveAlias(getSymbolOfDeclaration(node)); if (target !== unknownSymbol) { - const targetFlags = getAllSymbolFlags(target); + const targetFlags = getSymbolFlags(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); @@ -44594,7 +44606,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { markExportAsReferenced(node); } const target = symbol && (symbol.flags & SymbolFlags.Alias ? resolveAlias(symbol) : symbol); - if (!target || getAllSymbolFlags(target) & SymbolFlags.Value) { + if (!target || getSymbolFlags(target) & SymbolFlags.Value) { checkExpressionCached(node.propertyName || node.name); } } @@ -44650,7 +44662,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (sym) { 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 (getAllSymbolFlags(sym) & SymbolFlags.Value) { + 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)) { @@ -46157,7 +46169,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function isValue(s: Symbol): boolean { s = resolveSymbol(s); - return s && !!(getAllSymbolFlags(s) & SymbolFlags.Value); + return s && !!(getSymbolFlags(s) & SymbolFlags.Value); } } @@ -46312,7 +46324,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { case SyntaxKind.ImportSpecifier: case SyntaxKind.ExportSpecifier: const symbol = getSymbolOfDeclaration(node as ImportClause | NamespaceImport | ImportSpecifier | ExportSpecifier); - return !!symbol && isAliasResolvedToValue(symbol) && !getTypeOnlyAliasDeclaration(symbol, SymbolFlags.Value); + return !!symbol && isAliasResolvedToValue(symbol, /*excludeTypeOnlyValues*/ true); case SyntaxKind.ExportDeclaration: const exportClause = (node as ExportDeclaration).exportClause; return !!exportClause && ( @@ -46338,7 +46350,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return isValue && node.moduleReference && !nodeIsMissing(node.moduleReference); } - function isAliasResolvedToValue(symbol: Symbol | undefined): boolean { + function isAliasResolvedToValue(symbol: Symbol | undefined, excludeTypeOnlyValues?: boolean): boolean { if (!symbol) { return false; } @@ -46348,7 +46360,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } // 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 !!((getAllSymbolFlags(target) ?? -1) & SymbolFlags.Value) && + return !!(getSymbolFlags(symbol, excludeTypeOnlyValues, /*excludeLocalMeanings*/ true) & SymbolFlags.Value) && (shouldPreserveConstEnums(compilerOptions) || !isConstEnumOrConstEnumOnlyModule(target)); } @@ -46366,7 +46378,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } const target = getSymbolLinks(symbol).aliasTarget; if (target && getEffectiveModifierFlags(node) & ModifierFlags.Export && - getAllSymbolFlags(target) & SymbolFlags.Value && + getSymbolFlags(target) & SymbolFlags.Value && (shouldPreserveConstEnums(compilerOptions) || !isConstEnumOrConstEnumOnlyModule(target))) { // An `export import ... =` of a value symbol is always considered referenced return true; diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 56add913e2552..e8c8328a1b602 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3814,8 +3814,8 @@ export type TypeOnlyImportDeclaration = export type TypeOnlyExportDeclaration = | ExportSpecifier & ({ readonly isTypeOnly: true } | { readonly parent: NamedExports & { readonly parent: ExportDeclaration & { readonly isTypeOnly: true } } }) - | ExportDeclaration & { readonly isTypeOnly: true } // export * from "mod" - | NamespaceExport & { readonly parent: ExportDeclaration & { readonly isTypeOnly: true } } // export * as ns from "mod" + | ExportDeclaration & { readonly isTypeOnly: true, readonly moduleSpecifier: Expression } // export * from "mod" + | NamespaceExport & { readonly parent: ExportDeclaration & { readonly isTypeOnly: true, readonly moduleSpecifier: Expression } } // export * as ns from "mod" ; export type TypeOnlyAliasDeclaration = TypeOnlyImportDeclaration | TypeOnlyExportDeclaration; @@ -5878,7 +5878,7 @@ export interface SymbolLinks { deferralParent?: Type; // Source union/intersection of a deferred type cjsExportMerged?: Symbol; // Version of the symbol with all non export= exports merged with the export= target typeOnlyDeclaration?: TypeOnlyAliasDeclaration | false; // First resolved alias declaration that makes the symbol only usable in type constructs - typeOnlyExportStarMap?: Map<__String, ExportDeclaration & { readonly isTypeOnly: true }>; // Set on a module symbol when some of its exports were resolved through a 'export type * from "mod"' declaration + typeOnlyExportStarMap?: Map<__String, ExportDeclaration & { readonly isTypeOnly: true, readonly moduleSpecifier: Expression }>; // Set on a module symbol when some of its exports were resolved through a 'export type * from "mod"' declaration typeOnlyExportStarName?: __String; // Set to the name of the symbol re-exported by an 'export type *' declaration, when different from the symbol name isConstructorDeclaredProperty?: boolean; // Property declared through 'this.x = ...' assignment in constructor tupleLabelDeclaration?: NamedTupleMember | ParameterDeclaration; // Declaration associated with the tuple's label diff --git a/src/testRunner/unittests/services/transpile.ts b/src/testRunner/unittests/services/transpile.ts index cd6414bdf3360..ae05aaa9bcd92 100644 --- a/src/testRunner/unittests/services/transpile.ts +++ b/src/testRunner/unittests/services/transpile.ts @@ -620,4 +620,16 @@ export * as alias from './file';`, { testVerbatimModuleSyntax: true } ); + + transpilesCorrectly("Preserves exported const merged with type-only import", ` + import fooValue from "./values"; + import type {Foo} from "./types"; + + const Foo: Foo = fooValue as any as Foo; + + export {Foo}; + `, { + options: { compilerOptions: { module: ts.ModuleKind.ESNext, target: ts.ScriptTarget.ESNext } }, + testVerbatimModuleSyntax: true + }); }); diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 4b702907d6c69..8f578ea9af7e6 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -5827,9 +5827,11 @@ declare namespace ts { }; }) | ExportDeclaration & { readonly isTypeOnly: true; + readonly moduleSpecifier: Expression; } | NamespaceExport & { readonly parent: ExportDeclaration & { readonly isTypeOnly: true; + readonly moduleSpecifier: Expression; }; }; type TypeOnlyAliasDeclaration = TypeOnlyImportDeclaration | TypeOnlyExportDeclaration; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index a00cc6edf7731..51b1c167a2d48 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -1774,9 +1774,11 @@ declare namespace ts { }; }) | ExportDeclaration & { readonly isTypeOnly: true; + readonly moduleSpecifier: Expression; } | NamespaceExport & { readonly parent: ExportDeclaration & { readonly isTypeOnly: true; + readonly moduleSpecifier: Expression; }; }; type TypeOnlyAliasDeclaration = TypeOnlyImportDeclaration | TypeOnlyExportDeclaration; diff --git a/tests/baselines/reference/importElisionExportNonExportAndDefault.symbols b/tests/baselines/reference/importElisionExportNonExportAndDefault.symbols index cb6d6eed52ece..d2f46dd577969 100644 --- a/tests/baselines/reference/importElisionExportNonExportAndDefault.symbols +++ b/tests/baselines/reference/importElisionExportNonExportAndDefault.symbols @@ -5,6 +5,7 @@ import MyFunction from "./MyComponent"; >MyFunction : Symbol(MyFunction, Decl(main.ts, 0, 6)) MyFunction({msg: "Hello World"}); +>MyFunction : Symbol(MyFunction, Decl(main.ts, 0, 6)) >msg : Symbol(msg, Decl(main.ts, 2, 12)) diff --git a/tests/baselines/reference/importEquals3.js b/tests/baselines/reference/importEquals3.js index d49e222c86521..fa84a01466037 100644 --- a/tests/baselines/reference/importEquals3.js +++ b/tests/baselines/reference/importEquals3.js @@ -33,7 +33,9 @@ exports.A = A; //// [b.js] "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -exports.x = void 0; +exports.x = exports.A = void 0; +var A = a.A; // Error +exports.A = A; var x = 0; exports.x = x; //// [c.js] diff --git a/tests/baselines/reference/namespaceImportTypeQuery2.js b/tests/baselines/reference/namespaceImportTypeQuery2.js new file mode 100644 index 0000000000000..76be90d8beb87 --- /dev/null +++ b/tests/baselines/reference/namespaceImportTypeQuery2.js @@ -0,0 +1,43 @@ +//// [tests/cases/conformance/externalModules/typeOnly/namespaceImportTypeQuery2.ts] //// + +//// [z.ts] +interface A {} +export type { A }; + +//// [a.ts] +import { A } from './z'; +const A = 0; +export { A }; +export class B {}; + +//// [b.ts] +import * as types from './a'; +let t: typeof types = { + A: undefined as any, // ok + B: undefined as any, +} + + +//// [z.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +//// [a.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.B = exports.A = void 0; +var A = 0; +exports.A = A; +var B = /** @class */ (function () { + function B() { + } + return B; +}()); +exports.B = B; +; +//// [b.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var t = { + A: undefined, + B: undefined, +}; diff --git a/tests/baselines/reference/namespaceImportTypeQuery2.symbols b/tests/baselines/reference/namespaceImportTypeQuery2.symbols new file mode 100644 index 0000000000000..f881c9fd8d8b0 --- /dev/null +++ b/tests/baselines/reference/namespaceImportTypeQuery2.symbols @@ -0,0 +1,39 @@ +//// [tests/cases/conformance/externalModules/typeOnly/namespaceImportTypeQuery2.ts] //// + +=== /z.ts === +interface A {} +>A : Symbol(A, Decl(z.ts, 0, 0)) + +export type { A }; +>A : Symbol(A, Decl(z.ts, 1, 13)) + +=== /a.ts === +import { A } from './z'; +>A : Symbol(A, Decl(a.ts, 0, 8), Decl(a.ts, 1, 5)) + +const A = 0; +>A : Symbol(A, Decl(a.ts, 0, 8), Decl(a.ts, 1, 5)) + +export { A }; +>A : Symbol(A, Decl(a.ts, 2, 8)) + +export class B {}; +>B : Symbol(B, Decl(a.ts, 2, 13)) + +=== /b.ts === +import * as types from './a'; +>types : Symbol(types, Decl(b.ts, 0, 6)) + +let t: typeof types = { +>t : Symbol(t, Decl(b.ts, 1, 3)) +>types : Symbol(types, Decl(b.ts, 0, 6)) + + A: undefined as any, // ok +>A : Symbol(A, Decl(b.ts, 1, 23)) +>undefined : Symbol(undefined) + + B: undefined as any, +>B : Symbol(B, Decl(b.ts, 2, 22)) +>undefined : Symbol(undefined) +} + diff --git a/tests/baselines/reference/namespaceImportTypeQuery2.types b/tests/baselines/reference/namespaceImportTypeQuery2.types new file mode 100644 index 0000000000000..a1da638e79b60 --- /dev/null +++ b/tests/baselines/reference/namespaceImportTypeQuery2.types @@ -0,0 +1,41 @@ +//// [tests/cases/conformance/externalModules/typeOnly/namespaceImportTypeQuery2.ts] //// + +=== /z.ts === +interface A {} +export type { A }; +>A : A + +=== /a.ts === +import { A } from './z'; +>A : 0 + +const A = 0; +>A : 0 +>0 : 0 + +export { A }; +>A : 0 + +export class B {}; +>B : B + +=== /b.ts === +import * as types from './a'; +>types : typeof types + +let t: typeof types = { +>t : typeof types +>types : typeof types +>{ A: undefined as any, // ok B: undefined as any,} : { A: any; B: any; } + + A: undefined as any, // ok +>A : any +>undefined as any : any +>undefined : undefined + + B: undefined as any, +>B : any +>undefined as any : any +>undefined : undefined +} + diff --git a/tests/baselines/reference/namespaceImportTypeQuery3.errors.txt b/tests/baselines/reference/namespaceImportTypeQuery3.errors.txt new file mode 100644 index 0000000000000..d22ed64a2a543 --- /dev/null +++ b/tests/baselines/reference/namespaceImportTypeQuery3.errors.txt @@ -0,0 +1,18 @@ +/a.ts(1,24): error TS2307: Cannot find module './z' or its corresponding type declarations. + + +==== /a.ts (1 errors) ==== + import type { A } from './z'; // unresolved + ~~~~~ +!!! error TS2307: Cannot find module './z' or its corresponding type declarations. + const A = 0; + export { A }; + export class B {}; + +==== /b.ts (0 errors) ==== + import * as types from './a'; + let t: typeof types = { + A: undefined as any, // ok + B: undefined as any, + } + \ No newline at end of file diff --git a/tests/baselines/reference/namespaceImportTypeQuery3.js b/tests/baselines/reference/namespaceImportTypeQuery3.js new file mode 100644 index 0000000000000..d206a9fc2c72a --- /dev/null +++ b/tests/baselines/reference/namespaceImportTypeQuery3.js @@ -0,0 +1,36 @@ +//// [tests/cases/conformance/externalModules/typeOnly/namespaceImportTypeQuery3.ts] //// + +//// [a.ts] +import type { A } from './z'; // unresolved +const A = 0; +export { A }; +export class B {}; + +//// [b.ts] +import * as types from './a'; +let t: typeof types = { + A: undefined as any, // ok + B: undefined as any, +} + + +//// [a.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.B = exports.A = void 0; +var A = 0; +exports.A = A; +var B = /** @class */ (function () { + function B() { + } + return B; +}()); +exports.B = B; +; +//// [b.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var t = { + A: undefined, + B: undefined, +}; diff --git a/tests/baselines/reference/namespaceImportTypeQuery3.symbols b/tests/baselines/reference/namespaceImportTypeQuery3.symbols new file mode 100644 index 0000000000000..6f495340a41d1 --- /dev/null +++ b/tests/baselines/reference/namespaceImportTypeQuery3.symbols @@ -0,0 +1,32 @@ +//// [tests/cases/conformance/externalModules/typeOnly/namespaceImportTypeQuery3.ts] //// + +=== /a.ts === +import type { A } from './z'; // unresolved +>A : Symbol(A, Decl(a.ts, 0, 13), Decl(a.ts, 1, 5)) + +const A = 0; +>A : Symbol(A, Decl(a.ts, 0, 13), Decl(a.ts, 1, 5)) + +export { A }; +>A : Symbol(A, Decl(a.ts, 2, 8)) + +export class B {}; +>B : Symbol(B, Decl(a.ts, 2, 13)) + +=== /b.ts === +import * as types from './a'; +>types : Symbol(types, Decl(b.ts, 0, 6)) + +let t: typeof types = { +>t : Symbol(t, Decl(b.ts, 1, 3)) +>types : Symbol(types, Decl(b.ts, 0, 6)) + + A: undefined as any, // ok +>A : Symbol(A, Decl(b.ts, 1, 23)) +>undefined : Symbol(undefined) + + B: undefined as any, +>B : Symbol(B, Decl(b.ts, 2, 22)) +>undefined : Symbol(undefined) +} + diff --git a/tests/baselines/reference/namespaceImportTypeQuery3.types b/tests/baselines/reference/namespaceImportTypeQuery3.types new file mode 100644 index 0000000000000..859888541b21f --- /dev/null +++ b/tests/baselines/reference/namespaceImportTypeQuery3.types @@ -0,0 +1,36 @@ +//// [tests/cases/conformance/externalModules/typeOnly/namespaceImportTypeQuery3.ts] //// + +=== /a.ts === +import type { A } from './z'; // unresolved +>A : any + +const A = 0; +>A : 0 +>0 : 0 + +export { A }; +>A : 0 + +export class B {}; +>B : B + +=== /b.ts === +import * as types from './a'; +>types : typeof types + +let t: typeof types = { +>t : typeof types +>types : typeof types +>{ A: undefined as any, // ok B: undefined as any,} : { A: any; B: any; } + + A: undefined as any, // ok +>A : any +>undefined as any : any +>undefined : undefined + + B: undefined as any, +>B : any +>undefined as any : any +>undefined : undefined +} + diff --git a/tests/baselines/reference/namespaceImportTypeQuery4.errors.txt b/tests/baselines/reference/namespaceImportTypeQuery4.errors.txt new file mode 100644 index 0000000000000..bed29537a36ab --- /dev/null +++ b/tests/baselines/reference/namespaceImportTypeQuery4.errors.txt @@ -0,0 +1,23 @@ +/a.ts(1,24): error TS2307: Cannot find module './z' or its corresponding type declarations. +/b.ts(3,3): error TS2322: Type '{ A: any; B: any; }' is not assignable to type 'typeof import("/a")'. + Object literal may only specify known properties, and 'A' does not exist in type 'typeof import("/a")'. + + +==== /a.ts (1 errors) ==== + import type { A } from './z'; // unresolved + ~~~~~ +!!! error TS2307: Cannot find module './z' or its corresponding type declarations. + type A = 0; + export { A }; + export class B {}; + +==== /b.ts (1 errors) ==== + import * as types from './a'; + let t: typeof types = { + A: undefined as any, // error + ~ +!!! error TS2322: Type '{ A: any; B: any; }' is not assignable to type 'typeof import("/a")'. +!!! error TS2322: Object literal may only specify known properties, and 'A' does not exist in type 'typeof import("/a")'. + B: undefined as any, + } + \ No newline at end of file diff --git a/tests/baselines/reference/namespaceImportTypeQuery4.js b/tests/baselines/reference/namespaceImportTypeQuery4.js new file mode 100644 index 0000000000000..0390f53721872 --- /dev/null +++ b/tests/baselines/reference/namespaceImportTypeQuery4.js @@ -0,0 +1,34 @@ +//// [tests/cases/conformance/externalModules/typeOnly/namespaceImportTypeQuery4.ts] //// + +//// [a.ts] +import type { A } from './z'; // unresolved +type A = 0; +export { A }; +export class B {}; + +//// [b.ts] +import * as types from './a'; +let t: typeof types = { + A: undefined as any, // error + B: undefined as any, +} + + +//// [a.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.B = void 0; +var B = /** @class */ (function () { + function B() { + } + return B; +}()); +exports.B = B; +; +//// [b.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +var t = { + A: undefined, + B: undefined, +}; diff --git a/tests/baselines/reference/namespaceImportTypeQuery4.symbols b/tests/baselines/reference/namespaceImportTypeQuery4.symbols new file mode 100644 index 0000000000000..a54084063104f --- /dev/null +++ b/tests/baselines/reference/namespaceImportTypeQuery4.symbols @@ -0,0 +1,32 @@ +//// [tests/cases/conformance/externalModules/typeOnly/namespaceImportTypeQuery4.ts] //// + +=== /a.ts === +import type { A } from './z'; // unresolved +>A : Symbol(A, Decl(a.ts, 0, 13), Decl(a.ts, 0, 29)) + +type A = 0; +>A : Symbol(A, Decl(a.ts, 0, 13), Decl(a.ts, 0, 29)) + +export { A }; +>A : Symbol(A, Decl(a.ts, 2, 8)) + +export class B {}; +>B : Symbol(B, Decl(a.ts, 2, 13)) + +=== /b.ts === +import * as types from './a'; +>types : Symbol(types, Decl(b.ts, 0, 6)) + +let t: typeof types = { +>t : Symbol(t, Decl(b.ts, 1, 3)) +>types : Symbol(types, Decl(b.ts, 0, 6)) + + A: undefined as any, // error +>A : Symbol(A, Decl(b.ts, 1, 23)) +>undefined : Symbol(undefined) + + B: undefined as any, +>B : Symbol(B, Decl(b.ts, 2, 22)) +>undefined : Symbol(undefined) +} + diff --git a/tests/baselines/reference/namespaceImportTypeQuery4.types b/tests/baselines/reference/namespaceImportTypeQuery4.types new file mode 100644 index 0000000000000..6a13c1a8f014a --- /dev/null +++ b/tests/baselines/reference/namespaceImportTypeQuery4.types @@ -0,0 +1,35 @@ +//// [tests/cases/conformance/externalModules/typeOnly/namespaceImportTypeQuery4.ts] //// + +=== /a.ts === +import type { A } from './z'; // unresolved +>A : 0 + +type A = 0; +>A : 0 + +export { A }; +>A : any + +export class B {}; +>B : B + +=== /b.ts === +import * as types from './a'; +>types : typeof types + +let t: typeof types = { +>t : typeof types +>types : typeof types +>{ A: undefined as any, // error B: undefined as any,} : { A: any; B: any; } + + A: undefined as any, // error +>A : any +>undefined as any : any +>undefined : undefined + + B: undefined as any, +>B : any +>undefined as any : any +>undefined : undefined +} + diff --git a/tests/baselines/reference/transpile/Preserves exported const merged with type-only import (verbatimModuleSyntax=true).js b/tests/baselines/reference/transpile/Preserves exported const merged with type-only import (verbatimModuleSyntax=true).js new file mode 100644 index 0000000000000..c1a35b90eb2e2 --- /dev/null +++ b/tests/baselines/reference/transpile/Preserves exported const merged with type-only import (verbatimModuleSyntax=true).js @@ -0,0 +1,4 @@ +import fooValue from "./values"; +const Foo = fooValue; +export { Foo }; +//# sourceMappingURL=file.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Preserves exported const merged with type-only import (verbatimModuleSyntax=true).oldTranspile.js b/tests/baselines/reference/transpile/Preserves exported const merged with type-only import (verbatimModuleSyntax=true).oldTranspile.js new file mode 100644 index 0000000000000..c1a35b90eb2e2 --- /dev/null +++ b/tests/baselines/reference/transpile/Preserves exported const merged with type-only import (verbatimModuleSyntax=true).oldTranspile.js @@ -0,0 +1,4 @@ +import fooValue from "./values"; +const Foo = fooValue; +export { Foo }; +//# sourceMappingURL=file.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Preserves exported const merged with type-only import.js b/tests/baselines/reference/transpile/Preserves exported const merged with type-only import.js new file mode 100644 index 0000000000000..c1a35b90eb2e2 --- /dev/null +++ b/tests/baselines/reference/transpile/Preserves exported const merged with type-only import.js @@ -0,0 +1,4 @@ +import fooValue from "./values"; +const Foo = fooValue; +export { Foo }; +//# sourceMappingURL=file.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Preserves exported const merged with type-only import.oldTranspile.js b/tests/baselines/reference/transpile/Preserves exported const merged with type-only import.oldTranspile.js new file mode 100644 index 0000000000000..c1a35b90eb2e2 --- /dev/null +++ b/tests/baselines/reference/transpile/Preserves exported const merged with type-only import.oldTranspile.js @@ -0,0 +1,4 @@ +import fooValue from "./values"; +const Foo = fooValue; +export { Foo }; +//# sourceMappingURL=file.js.map \ No newline at end of file diff --git a/tests/baselines/reference/typeOnlyMerge3.js b/tests/baselines/reference/typeOnlyMerge3.js index 21c0e67554ad2..44e0443fe5ff9 100644 --- a/tests/baselines/reference/typeOnlyMerge3.js +++ b/tests/baselines/reference/typeOnlyMerge3.js @@ -25,13 +25,15 @@ function A() { } //// [b.js] "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); +exports.A = void 0; var A; (function (A) { A.displayName = "A"; -})(A || (A = {})); +})(A || (exports.A = A = {})); //// [c.js] "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); +var b_1 = require("./b"); A; A.displayName; A(); diff --git a/tests/cases/conformance/externalModules/typeOnly/namespaceImportTypeQuery2.ts b/tests/cases/conformance/externalModules/typeOnly/namespaceImportTypeQuery2.ts new file mode 100644 index 0000000000000..5ff13df84af1a --- /dev/null +++ b/tests/cases/conformance/externalModules/typeOnly/namespaceImportTypeQuery2.ts @@ -0,0 +1,16 @@ +// @Filename: /z.ts +interface A {} +export type { A }; + +// @Filename: /a.ts +import { A } from './z'; +const A = 0; +export { A }; +export class B {}; + +// @Filename: /b.ts +import * as types from './a'; +let t: typeof types = { + A: undefined as any, // ok + B: undefined as any, +} diff --git a/tests/cases/conformance/externalModules/typeOnly/namespaceImportTypeQuery3.ts b/tests/cases/conformance/externalModules/typeOnly/namespaceImportTypeQuery3.ts new file mode 100644 index 0000000000000..2e564378a6d30 --- /dev/null +++ b/tests/cases/conformance/externalModules/typeOnly/namespaceImportTypeQuery3.ts @@ -0,0 +1,12 @@ +// @Filename: /a.ts +import type { A } from './z'; // unresolved +const A = 0; +export { A }; +export class B {}; + +// @Filename: /b.ts +import * as types from './a'; +let t: typeof types = { + A: undefined as any, // ok + B: undefined as any, +} diff --git a/tests/cases/conformance/externalModules/typeOnly/namespaceImportTypeQuery4.ts b/tests/cases/conformance/externalModules/typeOnly/namespaceImportTypeQuery4.ts new file mode 100644 index 0000000000000..80fefc23ad8b7 --- /dev/null +++ b/tests/cases/conformance/externalModules/typeOnly/namespaceImportTypeQuery4.ts @@ -0,0 +1,12 @@ +// @Filename: /a.ts +import type { A } from './z'; // unresolved +type A = 0; +export { A }; +export class B {}; + +// @Filename: /b.ts +import * as types from './a'; +let t: typeof types = { + A: undefined as any, // error + B: undefined as any, +}