@@ -8533,11 +8533,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
85338533 ...oldcontext,
85348534 usedSymbolNames: new Set(oldcontext.usedSymbolNames),
85358535 remappedSymbolNames: new Map(),
8536+ remappedSymbolReferences: new Map(oldcontext.remappedSymbolReferences?.entries()),
85368537 tracker: undefined!,
85378538 };
85388539 const tracker: SymbolTracker = {
85398540 ...oldcontext.tracker.inner,
85408541 trackSymbol: (sym, decl, meaning) => {
8542+ if (context.remappedSymbolNames?.has(getSymbolId(sym))) return false; // If the context has a remapped name for the symbol, it *should* mean it's been made visible
85418543 const accessibleResult = isSymbolAccessible(sym, decl, meaning, /*shouldComputeAliasesToMakeVisible*/ false);
85428544 if (accessibleResult.accessibility === SymbolAccessibility.Accessible) {
85438545 // Lookup the root symbol of the chain of refs we'll use to access it and serialize it
@@ -8790,9 +8792,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
87908792 // If it's a property: emit `export default _default` with a `_default` prop
87918793 // If it's a class/interface/function: emit a class/interface/function with a `default` modifier
87928794 // These forms can merge, eg (`export default 12; export default interface A {}`)
8793- function serializeSymbolWorker(symbol: Symbol, isPrivate: boolean, propertyAsAlias: boolean): void {
8794- const symbolName = unescapeLeadingUnderscores(symbol.escapedName );
8795- const isDefault = symbol.escapedName === InternalSymbolName.Default;
8795+ function serializeSymbolWorker(symbol: Symbol, isPrivate: boolean, propertyAsAlias: boolean, escapedSymbolName = symbol.escapedName ): void {
8796+ const symbolName = unescapeLeadingUnderscores(escapedSymbolName );
8797+ const isDefault = escapedSymbolName === InternalSymbolName.Default;
87968798 if (isPrivate && !(context.flags & NodeBuilderFlags.AllowAnonymousIdentifier) && isStringANonContextualKeyword(symbolName) && !isDefault) {
87978799 // Oh no. We cannot use this symbol's name as it's name... It's likely some jsdoc had an invalid name like `export` or `default` :(
87988800 context.encounteredError = true;
@@ -8811,7 +8813,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
88118813 const modifierFlags = (!isPrivate ? ModifierFlags.Export : 0) | (isDefault && !needsPostExportDefault ? ModifierFlags.Default : 0);
88128814 const isConstMergedWithNS = symbol.flags & SymbolFlags.Module &&
88138815 symbol.flags & (SymbolFlags.BlockScopedVariable | SymbolFlags.FunctionScopedVariable | SymbolFlags.Property) &&
8814- symbol.escapedName !== InternalSymbolName.ExportEquals;
8816+ escapedSymbolName !== InternalSymbolName.ExportEquals;
88158817 const isConstMergedWithNSPrintableAsSignatureMerge = isConstMergedWithNS && isTypeRepresentableAsFunctionNamespaceMerge(getTypeOfSymbol(symbol), symbol);
88168818 if (symbol.flags & (SymbolFlags.Function | SymbolFlags.Method) || isConstMergedWithNSPrintableAsSignatureMerge) {
88178819 serializeAsFunctionNamespaceMerge(getTypeOfSymbol(symbol), symbol, getInternalSymbolName(symbol, symbolName), modifierFlags);
@@ -8823,7 +8825,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
88238825 // symbol of name `export=` which needs to be handled like an alias. It's not great, but it is what it is.
88248826 if (
88258827 symbol.flags & (SymbolFlags.BlockScopedVariable | SymbolFlags.FunctionScopedVariable | SymbolFlags.Property | SymbolFlags.Accessor)
8826- && symbol.escapedName !== InternalSymbolName.ExportEquals
8828+ && escapedSymbolName !== InternalSymbolName.ExportEquals
88278829 && !(symbol.flags & SymbolFlags.Prototype)
88288830 && !(symbol.flags & SymbolFlags.Class)
88298831 && !(symbol.flags & SymbolFlags.Method)
@@ -8839,7 +8841,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
88398841 else {
88408842 const type = getTypeOfSymbol(symbol);
88418843 const localName = getInternalSymbolName(symbol, symbolName);
8842- if (!(symbol.flags & SymbolFlags.Function) && isTypeRepresentableAsFunctionNamespaceMerge(type, symbol)) {
8844+ if (type.symbol && type.symbol !== symbol && type.symbol.flags & SymbolFlags.Function && some(type.symbol.declarations, isFunctionExpressionOrArrowFunction) && (type.symbol.members?.size || type.symbol.exports?.size)) {
8845+ // assignment of a anonymous expando/class-like function, the func/ns/merge branch below won't trigger,
8846+ // and the assignment form has to reference the unreachable anonymous type so will error.
8847+ // Instead, serialize the type's symbol, but with the current symbol's name, rather than the anonymous one.
8848+ if (!context.remappedSymbolReferences) {
8849+ context.remappedSymbolReferences = new Map();
8850+ }
8851+ context.remappedSymbolReferences.set(getSymbolId(type.symbol), symbol); // save name remapping as local name for target symbol
8852+ serializeSymbolWorker(type.symbol, isPrivate, propertyAsAlias, escapedSymbolName);
8853+ context.remappedSymbolReferences.delete(getSymbolId(type.symbol));
8854+ }
8855+ else if (!(symbol.flags & SymbolFlags.Function) && isTypeRepresentableAsFunctionNamespaceMerge(type, symbol)) {
88438856 // If the type looks like a function declaration + ns could represent it, and it's type is sourced locally, rewrite it into a function declaration + ns
88448857 serializeAsFunctionNamespaceMerge(type, symbol, localName, modifierFlags);
88458858 }
@@ -10159,6 +10172,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1015910172 * It will also use a representation of a number as written instead of a decimal form, e.g. `0o11` instead of `9`.
1016010173 */
1016110174 function getNameOfSymbolAsWritten(symbol: Symbol, context?: NodeBuilderContext): string {
10175+ if (context?.remappedSymbolReferences?.has(getSymbolId(symbol))) {
10176+ symbol = context.remappedSymbolReferences.get(getSymbolId(symbol))!;
10177+ }
1016210178 if (
1016310179 context && symbol.escapedName === InternalSymbolName.Default && !(context.flags & NodeBuilderFlags.UseAliasDefinedOutsideCurrentScope) &&
1016410180 // If it's not the first part of an entity name, it must print as `default`
@@ -49986,6 +50002,7 @@ interface NodeBuilderContext {
4998650002 typeParameterNamesByTextNextNameCount?: Map<string, number>;
4998750003 usedSymbolNames?: Set<string>;
4998850004 remappedSymbolNames?: Map<SymbolId, string>;
50005+ remappedSymbolReferences?: Map<SymbolId, Symbol>;
4998950006 reverseMappedStack?: ReverseMappedSymbol[];
4999050007}
4999150008
0 commit comments