@@ -64,7 +64,7 @@ namespace ts {
64
64
const languageVersion = getEmitScriptTarget(compilerOptions);
65
65
const modulekind = getEmitModuleKind(compilerOptions);
66
66
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) ;
68
68
const strictNullChecks = getStrictOptionValue(compilerOptions, "strictNullChecks");
69
69
const strictFunctionTypes = getStrictOptionValue(compilerOptions, "strictFunctionTypes");
70
70
const noImplicitAny = getStrictOptionValue(compilerOptions, "noImplicitAny");
@@ -1431,6 +1431,43 @@ namespace ts {
1431
1431
return getSymbolOfPartOfRightHandSideOfImportEquals(<EntityName>node.moduleReference, dontResolveAlias);
1432
1432
}
1433
1433
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
+
1434
1471
function getTargetOfImportClause(node: ImportClause, dontResolveAlias: boolean): Symbol {
1435
1472
const moduleSymbol = resolveExternalModuleName(node, (<ImportDeclaration>node.parent).moduleSpecifier);
1436
1473
@@ -1440,22 +1477,26 @@ namespace ts {
1440
1477
exportDefaultSymbol = moduleSymbol;
1441
1478
}
1442
1479
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);
1447
1481
}
1448
1482
1449
- if (!exportDefaultSymbol && !allowSyntheticDefaultImports) {
1483
+ const file = forEach(moduleSymbol.declarations, sourceFileOrUndefined);
1484
+ const hasSyntheticDefault = canHaveSyntheticDefault(file, moduleSymbol, dontResolveAlias);
1485
+ if (!exportDefaultSymbol && !hasSyntheticDefault) {
1450
1486
error(node.name, Diagnostics.Module_0_has_no_default_export, symbolToString(moduleSymbol));
1451
1487
}
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
1453
1490
return resolveExternalModuleSymbol(moduleSymbol, dontResolveAlias) || resolveSymbol(moduleSymbol, dontResolveAlias);
1454
1491
}
1455
1492
return exportDefaultSymbol;
1456
1493
}
1457
1494
}
1458
1495
1496
+ function sourceFileOrUndefined(d: Declaration) {
1497
+ return isSourceFile(d) ? d : undefined;
1498
+ }
1499
+
1459
1500
function getTargetOfNamespaceImport(node: NamespaceImport, dontResolveAlias: boolean): Symbol {
1460
1501
const moduleSpecifier = (<ImportDeclaration>node.parent.parent).moduleSpecifier;
1461
1502
return resolveESModuleSymbol(resolveExternalModuleName(node, moduleSpecifier), moduleSpecifier, dontResolveAlias);
@@ -1851,8 +1892,11 @@ namespace ts {
1851
1892
error(moduleReferenceExpression, Diagnostics.Module_0_resolves_to_a_non_module_entity_and_cannot_be_imported_using_this_construct, symbolToString(moduleSymbol));
1852
1893
return symbol;
1853
1894
}
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
+ ) {
1856
1900
const type = getTypeOfSymbol(symbol);
1857
1901
let sigs = getSignaturesOfStructuredType(type, SignatureKind.Call);
1858
1902
if (!sigs || !sigs.length) {
@@ -1864,7 +1908,7 @@ namespace ts {
1864
1908
result.declarations = symbol.declarations ? symbol.declarations.slice() : [];
1865
1909
result.parent = symbol.parent;
1866
1910
result.target = symbol;
1867
- result.originatingImport = referenaceParent as ImportDeclaration;
1911
+ result.originatingImport = referenceParent as ImportDeclaration | ImportCall ;
1868
1912
if (symbol.valueDeclaration) result.valueDeclaration = symbol.valueDeclaration;
1869
1913
if (symbol.constEnumOnlyModule) result.constEnumOnlyModule = true;
1870
1914
if (symbol.members) result.members = cloneMap(symbol.members);
@@ -8983,7 +9027,7 @@ namespace ts {
8983
9027
// Check if we should issue an extra diagnostic to produce a quickfix for a slightly incorrect import statement
8984
9028
if (headMessage && errorNode && !answer && source.symbol) {
8985
9029
const links = getSymbolLinks(source.symbol);
8986
- if (links.originatingImport) {
9030
+ if (links.originatingImport && !isImportCall(links.originatingImport) ) {
8987
9031
const helpfulRetry = checkTypeRelatedTo(getTypeOfSymbol(links.target), target, relation, /*errorNode*/ undefined);
8988
9032
if (helpfulRetry) {
8989
9033
// Likely an incorrect import. Issue a helpful diagnostic to produce a quickfix to change the import
@@ -16800,10 +16844,16 @@ namespace ts {
16800
16844
}
16801
16845
16802
16846
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)) {
16804
16854
const sigs = getSignaturesOfType(getTypeOfSymbol(getSymbolLinks(apparentType.symbol).target), kind);
16805
16855
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);
16807
16857
}
16808
16858
}
16809
16859
@@ -17112,25 +17162,26 @@ namespace ts {
17112
17162
if (moduleSymbol) {
17113
17163
const esModuleSymbol = resolveESModuleSymbol(moduleSymbol, specifier, /*dontRecursivelyResolve*/ true);
17114
17164
if (esModuleSymbol) {
17115
- return createPromiseReturnType(node, getTypeWithSyntheticDefaultImportType(getTypeOfSymbol(esModuleSymbol), esModuleSymbol));
17165
+ return createPromiseReturnType(node, getTypeWithSyntheticDefaultImportType(getTypeOfSymbol(esModuleSymbol), esModuleSymbol, moduleSymbol ));
17116
17166
}
17117
17167
}
17118
17168
return createPromiseReturnType(node, anyType);
17119
17169
}
17120
17170
17121
- function getTypeWithSyntheticDefaultImportType(type: Type, symbol: Symbol): Type {
17171
+ function getTypeWithSyntheticDefaultImportType(type: Type, symbol: Symbol, originalSymbol: Symbol ): Type {
17122
17172
if (allowSyntheticDefaultImports && type && type !== unknownType) {
17123
17173
const synthType = type as SyntheticDefaultModuleType;
17124
17174
if (!synthType.syntheticType) {
17125
- if (!getPropertyOfType(type, InternalSymbolName.Default)) {
17175
+ const hasSyntheticDefault = canHaveSyntheticDefault(forEach(originalSymbol.declarations, sourceFileOrUndefined), originalSymbol, /*dontResolveAlias*/ false);
17176
+ if (hasSyntheticDefault) {
17126
17177
const memberTable = createSymbolTable();
17127
17178
const newSymbol = createSymbol(SymbolFlags.Alias, InternalSymbolName.Default);
17128
17179
newSymbol.target = resolveSymbol(symbol);
17129
17180
memberTable.set(InternalSymbolName.Default, newSymbol);
17130
17181
const anonymousSymbol = createSymbol(SymbolFlags.TypeLiteral, InternalSymbolName.Type);
17131
17182
const defaultContainingObject = createAnonymousType(anonymousSymbol, memberTable, emptyArray, emptyArray, /*stringIndexInfo*/ undefined, /*numberIndexInfo*/ undefined);
17132
17183
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 ;
17134
17185
}
17135
17186
else {
17136
17187
synthType.syntheticType = type;
0 commit comments