@@ -1744,15 +1744,23 @@ namespace ts {
17441744 return false;
17451745 }
17461746
1747- function isSymbolAccessible(symbol: Symbol, enclosingDeclaration: Node, meaning: SymbolFlags): SymbolAccessibilityResult {
1747+ /**
1748+ * Check if the given symbol in given enclosing declaration is accessible and mark all associated alias to be visible if requested
1749+ *
1750+ * @param symbol a Symbol to check if accessible
1751+ * @param enclosingDeclaration a Node containing reference to the symbol
1752+ * @param meaning a SymbolFlags to check if such meaning of the symbol is accessible
1753+ * @param shouldComputeAliasToMakeVisible a boolean value to indicate whether to return aliases to be mark visible in case the symbol is accessible
1754+ */
1755+ function isSymbolAccessible(symbol: Symbol, enclosingDeclaration: Node, meaning: SymbolFlags, shouldComputeAliasesToMakeVisible: boolean): SymbolAccessibilityResult {
17481756 if (symbol && enclosingDeclaration && !(symbol.flags & SymbolFlags.TypeParameter)) {
17491757 const initialSymbol = symbol;
17501758 let meaningToLook = meaning;
17511759 while (symbol) {
17521760 // Symbol is accessible if it by itself is accessible
17531761 const accessibleSymbolChain = getAccessibleSymbolChain(symbol, enclosingDeclaration, meaningToLook, /*useOnlyExternalAliasing*/ false);
17541762 if (accessibleSymbolChain) {
1755- const hasAccessibleDeclarations = hasVisibleDeclarations(accessibleSymbolChain[0]);
1763+ const hasAccessibleDeclarations = hasVisibleDeclarations(accessibleSymbolChain[0], shouldComputeAliasesToMakeVisible );
17561764 if (!hasAccessibleDeclarations) {
17571765 return <SymbolAccessibilityResult>{
17581766 accessibility: SymbolAccessibility.NotAccessible,
@@ -1816,7 +1824,7 @@ namespace ts {
18161824 return isAmbientModule(declaration) || (declaration.kind === SyntaxKind.SourceFile && isExternalOrCommonJsModule(<SourceFile>declaration));
18171825 }
18181826
1819- function hasVisibleDeclarations(symbol: Symbol): SymbolVisibilityResult {
1827+ function hasVisibleDeclarations(symbol: Symbol, shouldComputeAliasToMakeVisible: boolean ): SymbolVisibilityResult {
18201828 let aliasesToMakeVisible: AnyImportSyntax[];
18211829 if (forEach(symbol.declarations, declaration => !getIsDeclarationVisible(declaration))) {
18221830 return undefined;
@@ -1832,14 +1840,19 @@ namespace ts {
18321840 if (anyImportSyntax &&
18331841 !(anyImportSyntax.flags & NodeFlags.Export) && // import clause without export
18341842 isDeclarationVisible(<Declaration>anyImportSyntax.parent)) {
1835- getNodeLinks(declaration).isVisible = true;
1836- if (aliasesToMakeVisible) {
1837- if (!contains(aliasesToMakeVisible, anyImportSyntax)) {
1838- aliasesToMakeVisible.push(anyImportSyntax);
1843+ // In function "buildTypeDisplay" where we decide whether to write type-alias or serialize types,
1844+ // we want to just check if type- alias is accessible or not but we don't care about emitting those alias at that time
1845+ // since we will do the emitting later in trackSymbol.
1846+ if (shouldComputeAliasToMakeVisible) {
1847+ getNodeLinks(declaration).isVisible = true;
1848+ if (aliasesToMakeVisible) {
1849+ if (!contains(aliasesToMakeVisible, anyImportSyntax)) {
1850+ aliasesToMakeVisible.push(anyImportSyntax);
1851+ }
1852+ }
1853+ else {
1854+ aliasesToMakeVisible = [anyImportSyntax];
18391855 }
1840- }
1841- else {
1842- aliasesToMakeVisible = [anyImportSyntax];
18431856 }
18441857 return true;
18451858 }
@@ -1874,7 +1887,7 @@ namespace ts {
18741887 const symbol = resolveName(enclosingDeclaration, (<Identifier>firstIdentifier).text, meaning, /*nodeNotFoundErrorMessage*/ undefined, /*nameArg*/ undefined);
18751888
18761889 // Verify if the symbol is accessible
1877- return (symbol && hasVisibleDeclarations(symbol)) || <SymbolVisibilityResult>{
1890+ return (symbol && hasVisibleDeclarations(symbol, /*shouldComputeAliasToMakeVisible*/ true )) || <SymbolVisibilityResult>{
18781891 accessibility: SymbolAccessibility.NotAccessible,
18791892 errorSymbolName: getTextOfNode(firstIdentifier),
18801893 errorNode: firstIdentifier
@@ -2152,14 +2165,16 @@ namespace ts {
21522165 // The specified symbol flags need to be reinterpreted as type flags
21532166 buildSymbolDisplay(type.symbol, writer, enclosingDeclaration, SymbolFlags.Type, SymbolFormatFlags.None, nextFlags);
21542167 }
2155- else if (!(flags & TypeFormatFlags.InTypeAlias) && type.flags & (TypeFlags.Anonymous | TypeFlags.UnionOrIntersection) && type.aliasSymbol) {
2156- if (type.flags & TypeFlags.Anonymous || !(flags & TypeFormatFlags.UseTypeAliasValue)) {
2157- const typeArguments = type.aliasTypeArguments;
2158- writeSymbolTypeReference(type.aliasSymbol, typeArguments, 0, typeArguments ? typeArguments.length : 0, nextFlags);
2159- }
2160- else {
2161- writeUnionOrIntersectionType(<UnionOrIntersectionType>type, nextFlags);
2162- }
2168+ else if (!(flags & TypeFormatFlags.InTypeAlias) && ((type.flags & TypeFlags.Anonymous && !(<AnonymousType>type).target) || type.flags & TypeFlags.UnionOrIntersection) && type.aliasSymbol &&
2169+ isSymbolAccessible(type.aliasSymbol, enclosingDeclaration, SymbolFlags.Type, /*shouldComputeAliasesToMakeVisible*/ false).accessibility === SymbolAccessibility.Accessible) {
2170+ // We emit inferred type as type-alias at the current location if all the following is true
2171+ // the input type is has alias symbol that is accessible
2172+ // the input type is a union, intersection or anonymous type that is fully instantiated (if not we want to keep dive into)
2173+ // e.g.: export type Bar<X, Y> = () => [X, Y];
2174+ // export type Foo<Y> = Bar<any, Y>;
2175+ // export const y = (x: Foo<string>) => 1 // we want to emit as ...x: () => [any, string])
2176+ const typeArguments = type.aliasTypeArguments;
2177+ writeSymbolTypeReference(type.aliasSymbol, typeArguments, 0, typeArguments ? typeArguments.length : 0, nextFlags);
21632178 }
21642179 else if (type.flags & TypeFlags.UnionOrIntersection) {
21652180 writeUnionOrIntersectionType(<UnionOrIntersectionType>type, nextFlags);
0 commit comments