@@ -541,7 +541,7 @@ namespace ts {
541541 }
542542
543543 function declareModuleMember ( node : Declaration , symbolFlags : SymbolFlags , symbolExcludes : SymbolFlags ) : Symbol {
544- const hasExportModifier = getCombinedModifierFlags ( node ) & ModifierFlags . Export ;
544+ const hasExportModifier = ! ! ( getCombinedModifierFlags ( node ) & ModifierFlags . Export ) || jsdocTreatAsExported ( node ) ;
545545 if ( symbolFlags & SymbolFlags . Alias ) {
546546 if ( node . kind === SyntaxKind . ExportSpecifier || ( node . kind === SyntaxKind . ImportEqualsDeclaration && hasExportModifier ) ) {
547547 return declareSymbol ( container . symbol . exports ! , container . symbol , node , symbolFlags , symbolExcludes ) ;
@@ -567,7 +567,7 @@ namespace ts {
567567 // and this case is specially handled. Module augmentations should only be merged with original module definition
568568 // and should never be merged directly with other augmentation, and the latter case would be possible if automatic merge is allowed.
569569 if ( isJSDocTypeAlias ( node ) ) Debug . assert ( isInJSFile ( node ) ) ; // We shouldn't add symbols for JSDoc nodes if not in a JS file.
570- if ( ( ! isAmbientModule ( node ) && ( hasExportModifier || container . flags & NodeFlags . ExportContext ) ) || isJSDocTypeAlias ( node ) ) {
570+ if ( ! isAmbientModule ( node ) && ( hasExportModifier || container . flags & NodeFlags . ExportContext ) ) {
571571 if ( ! container . locals || ( hasSyntacticModifier ( node , ModifierFlags . Default ) && ! getDeclarationName ( node ) ) ) {
572572 return declareSymbol ( container . symbol . exports ! , container . symbol , node , symbolFlags , symbolExcludes ) ; // No local symbol for an unnamed default!
573573 }
@@ -583,6 +583,21 @@ namespace ts {
583583 }
584584 }
585585
586+ function jsdocTreatAsExported ( node : Node ) {
587+ if ( ! isJSDocTypeAlias ( node ) ) return false ;
588+ // jsdoc typedef handling is a bit of a doozy, but to summarize, treat the typedef as exported if:
589+ // 1. It has an explicit name (since by default typedefs are always directly exported, either at the top level or in a container), or
590+ if ( ! isJSDocEnumTag ( node ) && ! ! node . fullName ) return true ;
591+ // 2. The thing a nameless typedef pulls its name from is implicitly a direct export (either by assignment or actual export flag).
592+ const declName = getNameOfDeclaration ( node ) ;
593+ if ( ! declName ) return false ;
594+ if ( isPropertyAccessEntityNameExpression ( declName . parent ) && isTopLevelNamespaceAssignment ( declName . parent ) ) return true ;
595+ if ( isDeclaration ( declName . parent ) && getCombinedModifierFlags ( declName . parent ) & ModifierFlags . Export ) return true ;
596+ // This could potentially be simplified by having `delayedBindJSDocTypedefTag` pass in an override for `hasExportModifier`, since it should
597+ // already have calculated and branched on most of this.
598+ return false ;
599+ }
600+
586601 // All container nodes are kept on a linked list in declaration order. This list is used by
587602 // the getLocalNameOfContainer function in the type checker to validate that the local name
588603 // used for a container is unique.
0 commit comments