@@ -64,7 +64,7 @@ namespace ts {
6464 const languageVersion = getEmitScriptTarget(compilerOptions);
6565 const modulekind = getEmitModuleKind(compilerOptions);
6666 const noUnusedIdentifiers = !!compilerOptions.noUnusedLocals || !!compilerOptions.noUnusedParameters;
67- const allowSyntheticDefaultImports = typeof compilerOptions.allowSyntheticDefaultImports !== "undefined" ? compilerOptions.allowSyntheticDefaultImports : modulekind === ModuleKind.System ;
67+ const allowSyntheticDefaultImports = typeof compilerOptions.allowSyntheticDefaultImports !== "undefined" ? compilerOptions.allowSyntheticDefaultImports : ( modulekind && modulekind < ModuleKind.ES2015) ;
6868 const strictNullChecks = getStrictOptionValue(compilerOptions, "strictNullChecks");
6969 const strictFunctionTypes = getStrictOptionValue(compilerOptions, "strictFunctionTypes");
7070 const noImplicitAny = getStrictOptionValue(compilerOptions, "noImplicitAny");
@@ -1431,6 +1431,43 @@ namespace ts {
14311431 return getSymbolOfPartOfRightHandSideOfImportEquals(<EntityName>node.moduleReference, dontResolveAlias);
14321432 }
14331433
1434+ function resolveExportByName(moduleSymbol: Symbol, name: __String, dontResolveAlias: boolean) {
1435+ const exportValue = moduleSymbol.exports.get(InternalSymbolName.ExportEquals);
1436+ return exportValue
1437+ ? getPropertyOfType(getTypeOfSymbol(exportValue), name)
1438+ : resolveSymbol(moduleSymbol.exports.get(name), dontResolveAlias);
1439+ }
1440+
1441+ function canHaveSyntheticDefault(file: SourceFile | undefined, moduleSymbol: Symbol, dontResolveAlias: boolean) {
1442+ if (!allowSyntheticDefaultImports) {
1443+ return false;
1444+ }
1445+ // Declaration files (and ambient modules)
1446+ if (!file || file.isDeclarationFile) {
1447+ // Definitely cannot have a synthetic default if they have a default member specified
1448+ if (resolveExportByName(moduleSymbol, InternalSymbolName.Default, dontResolveAlias)) {
1449+ return false;
1450+ }
1451+ // It _might_ still be incorrect to assume there is no __esModule marker on the import at runtime, even if there is no `default` member
1452+ // So we check a bit more,
1453+ if (resolveExportByName(moduleSymbol, escapeLeadingUnderscores("__esModule"), dontResolveAlias)) {
1454+ // If there is an `__esModule` specified in the declaration (meaning someone explicitly added it or wrote it in their code),
1455+ // it definitely is a module and does not have a synthetic default
1456+ return false;
1457+ }
1458+ // There are _many_ declaration files not written with esmodules in mind that still get compiled into a format with __esModule set
1459+ // Meaning there may be no default at runtime - however to be on the permissive side, we allow access to a synthetic default member
1460+ // as there is no marker to indicate if the accompanying JS has `__esModule` or not, or is even native esm
1461+ return true;
1462+ }
1463+ // TypeScript files never have a synthetic default (as they are always emitted with an __esModule marker) _unless_ they contain an export= statement
1464+ if (!isSourceFileJavaScript(file)) {
1465+ return hasExportAssignmentSymbol(moduleSymbol);
1466+ }
1467+ // JS files have a synthetic default if they do not contain ES2015+ module syntax (export = is not valid in js) _and_ do not have an __esModule marker
1468+ return !file.externalModuleIndicator && !resolveExportByName(moduleSymbol, escapeLeadingUnderscores("__esModule"), dontResolveAlias);
1469+ }
1470+
14341471 function getTargetOfImportClause(node: ImportClause, dontResolveAlias: boolean): Symbol {
14351472 const moduleSymbol = resolveExternalModuleName(node, (<ImportDeclaration>node.parent).moduleSpecifier);
14361473
@@ -1440,22 +1477,26 @@ namespace ts {
14401477 exportDefaultSymbol = moduleSymbol;
14411478 }
14421479 else {
1443- const exportValue = moduleSymbol.exports.get("export=" as __String);
1444- exportDefaultSymbol = exportValue
1445- ? getPropertyOfType(getTypeOfSymbol(exportValue), "default" as __String)
1446- : resolveSymbol(moduleSymbol.exports.get("default" as __String), dontResolveAlias);
1480+ exportDefaultSymbol = resolveExportByName(moduleSymbol, InternalSymbolName.Default, dontResolveAlias);
14471481 }
14481482
1449- if (!exportDefaultSymbol && !allowSyntheticDefaultImports) {
1483+ const file = forEach(moduleSymbol.declarations, sourceFileOrUndefined);
1484+ const hasSyntheticDefault = canHaveSyntheticDefault(file, moduleSymbol, dontResolveAlias);
1485+ if (!exportDefaultSymbol && !hasSyntheticDefault) {
14501486 error(node.name, Diagnostics.Module_0_has_no_default_export, symbolToString(moduleSymbol));
14511487 }
1452- else if (!exportDefaultSymbol && allowSyntheticDefaultImports) {
1488+ else if (!exportDefaultSymbol && hasSyntheticDefault) {
1489+ // per emit behavior, a synthetic default overrides a "real" .default member if `__esModule` is not present
14531490 return resolveExternalModuleSymbol(moduleSymbol, dontResolveAlias) || resolveSymbol(moduleSymbol, dontResolveAlias);
14541491 }
14551492 return exportDefaultSymbol;
14561493 }
14571494 }
14581495
1496+ function sourceFileOrUndefined(d: Declaration) {
1497+ return isSourceFile(d) ? d : undefined;
1498+ }
1499+
14591500 function getTargetOfNamespaceImport(node: NamespaceImport, dontResolveAlias: boolean): Symbol {
14601501 const moduleSpecifier = (<ImportDeclaration>node.parent.parent).moduleSpecifier;
14611502 return resolveESModuleSymbol(resolveExternalModuleName(node, moduleSpecifier), moduleSpecifier, dontResolveAlias);
@@ -1851,8 +1892,11 @@ namespace ts {
18511892 error(moduleReferenceExpression, Diagnostics.Module_0_resolves_to_a_non_module_entity_and_cannot_be_imported_using_this_construct, symbolToString(moduleSymbol));
18521893 return symbol;
18531894 }
1854- const referenaceParent = moduleReferenceExpression.parent;
1855- if (referenaceParent.kind === SyntaxKind.ImportDeclaration && getNamespaceDeclarationNode(referenaceParent as ImportDeclaration)) {
1895+ const referenceParent = moduleReferenceExpression.parent;
1896+ if (
1897+ (referenceParent.kind === SyntaxKind.ImportDeclaration && getNamespaceDeclarationNode(referenceParent as ImportDeclaration)) ||
1898+ isImportCall(referenceParent)
1899+ ) {
18561900 const type = getTypeOfSymbol(symbol);
18571901 let sigs = getSignaturesOfStructuredType(type, SignatureKind.Call);
18581902 if (!sigs || !sigs.length) {
@@ -1864,7 +1908,7 @@ namespace ts {
18641908 result.declarations = symbol.declarations ? symbol.declarations.slice() : [];
18651909 result.parent = symbol.parent;
18661910 result.target = symbol;
1867- result.originatingImport = referenaceParent as ImportDeclaration;
1911+ result.originatingImport = referenceParent as ImportDeclaration | ImportCall ;
18681912 if (symbol.valueDeclaration) result.valueDeclaration = symbol.valueDeclaration;
18691913 if (symbol.constEnumOnlyModule) result.constEnumOnlyModule = true;
18701914 if (symbol.members) result.members = cloneMap(symbol.members);
@@ -8983,7 +9027,7 @@ namespace ts {
89839027 // Check if we should issue an extra diagnostic to produce a quickfix for a slightly incorrect import statement
89849028 if (headMessage && errorNode && !answer && source.symbol) {
89859029 const links = getSymbolLinks(source.symbol);
8986- if (links.originatingImport) {
9030+ if (links.originatingImport && !isImportCall(links.originatingImport) ) {
89879031 const helpfulRetry = checkTypeRelatedTo(getTypeOfSymbol(links.target), target, relation, /*errorNode*/ undefined);
89889032 if (helpfulRetry) {
89899033 // Likely an incorrect import. Issue a helpful diagnostic to produce a quickfix to change the import
@@ -16800,10 +16844,16 @@ namespace ts {
1680016844 }
1680116845
1680216846 function invocationErrorRecovery(apparentType: Type, kind: SignatureKind) {
16803- if (apparentType.symbol && getSymbolLinks(apparentType.symbol).originatingImport) {
16847+ if (!apparentType.symbol) {
16848+ return;
16849+ }
16850+ const importNode = getSymbolLinks(apparentType.symbol).originatingImport;
16851+ // Create a diagnostic on the originating import if possible onto which we can attach a quickfix
16852+ // An import call expression cannot be rewritten into another form to correct the error - the only solution is to use `.default` at the use-site
16853+ if (importNode && !isImportCall(importNode)) {
1680416854 const sigs = getSignaturesOfType(getTypeOfSymbol(getSymbolLinks(apparentType.symbol).target), kind);
1680516855 if (!sigs || !sigs.length) return;
16806- error(getSymbolLinks(apparentType.symbol).originatingImport , Diagnostics.Import_is_called_or_constructed_which_is_not_valid_ES2015_module_usage_and_will_fail_at_runtime);
16856+ error(importNode , Diagnostics.Import_is_called_or_constructed_which_is_not_valid_ES2015_module_usage_and_will_fail_at_runtime);
1680716857 }
1680816858 }
1680916859
@@ -17112,25 +17162,26 @@ namespace ts {
1711217162 if (moduleSymbol) {
1711317163 const esModuleSymbol = resolveESModuleSymbol(moduleSymbol, specifier, /*dontRecursivelyResolve*/ true);
1711417164 if (esModuleSymbol) {
17115- return createPromiseReturnType(node, getTypeWithSyntheticDefaultImportType(getTypeOfSymbol(esModuleSymbol), esModuleSymbol));
17165+ return createPromiseReturnType(node, getTypeWithSyntheticDefaultImportType(getTypeOfSymbol(esModuleSymbol), esModuleSymbol, moduleSymbol ));
1711617166 }
1711717167 }
1711817168 return createPromiseReturnType(node, anyType);
1711917169 }
1712017170
17121- function getTypeWithSyntheticDefaultImportType(type: Type, symbol: Symbol): Type {
17171+ function getTypeWithSyntheticDefaultImportType(type: Type, symbol: Symbol, originalSymbol: Symbol ): Type {
1712217172 if (allowSyntheticDefaultImports && type && type !== unknownType) {
1712317173 const synthType = type as SyntheticDefaultModuleType;
1712417174 if (!synthType.syntheticType) {
17125- if (!getPropertyOfType(type, InternalSymbolName.Default)) {
17175+ const hasSyntheticDefault = canHaveSyntheticDefault(forEach(originalSymbol.declarations, sourceFileOrUndefined), originalSymbol, /*dontResolveAlias*/ false);
17176+ if (hasSyntheticDefault) {
1712617177 const memberTable = createSymbolTable();
1712717178 const newSymbol = createSymbol(SymbolFlags.Alias, InternalSymbolName.Default);
1712817179 newSymbol.target = resolveSymbol(symbol);
1712917180 memberTable.set(InternalSymbolName.Default, newSymbol);
1713017181 const anonymousSymbol = createSymbol(SymbolFlags.TypeLiteral, InternalSymbolName.Type);
1713117182 const defaultContainingObject = createAnonymousType(anonymousSymbol, memberTable, emptyArray, emptyArray, /*stringIndexInfo*/ undefined, /*numberIndexInfo*/ undefined);
1713217183 anonymousSymbol.type = defaultContainingObject;
17133- synthType.syntheticType = getIntersectionType([ type, defaultContainingObject]) ;
17184+ synthType.syntheticType = ( type.flags & TypeFlags.StructuredType && type.symbol.flags & (SymbolFlags.Module | SymbolFlags.Variable)) ? getSpreadType(type , defaultContainingObject, anonymousSymbol, /*propegatedFlags*/ 0) : defaultContainingObject ;
1713417185 }
1713517186 else {
1713617187 synthType.syntheticType = type;
0 commit comments