@@ -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);
@@ -8993,7 +9037,7 @@ namespace ts {
8993
9037
// Check if we should issue an extra diagnostic to produce a quickfix for a slightly incorrect import statement
8994
9038
if (headMessage && errorNode && !answer && source.symbol) {
8995
9039
const links = getSymbolLinks(source.symbol);
8996
- if (links.originatingImport) {
9040
+ if (links.originatingImport && !isImportCall(links.originatingImport) ) {
8997
9041
const helpfulRetry = checkTypeRelatedTo(getTypeOfSymbol(links.target), target, relation, /*errorNode*/ undefined);
8998
9042
if (helpfulRetry) {
8999
9043
// Likely an incorrect import. Issue a helpful diagnostic to produce a quickfix to change the import
@@ -16814,10 +16858,16 @@ namespace ts {
16814
16858
}
16815
16859
16816
16860
function invocationErrorRecovery(apparentType: Type, kind: SignatureKind) {
16817
- if (apparentType.symbol && getSymbolLinks(apparentType.symbol).originatingImport) {
16861
+ if (!apparentType.symbol) {
16862
+ return;
16863
+ }
16864
+ const importNode = getSymbolLinks(apparentType.symbol).originatingImport;
16865
+ // Create a diagnostic on the originating import if possible onto which we can attach a quickfix
16866
+ // 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
16867
+ if (importNode && !isImportCall(importNode)) {
16818
16868
const sigs = getSignaturesOfType(getTypeOfSymbol(getSymbolLinks(apparentType.symbol).target), kind);
16819
16869
if (!sigs || !sigs.length) return;
16820
- error(getSymbolLinks(apparentType.symbol).originatingImport , Diagnostics.Import_is_called_or_constructed_which_is_not_valid_ES2015_module_usage_and_will_fail_at_runtime);
16870
+ error(importNode , Diagnostics.Import_is_called_or_constructed_which_is_not_valid_ES2015_module_usage_and_will_fail_at_runtime);
16821
16871
}
16822
16872
}
16823
16873
@@ -17126,25 +17176,26 @@ namespace ts {
17126
17176
if (moduleSymbol) {
17127
17177
const esModuleSymbol = resolveESModuleSymbol(moduleSymbol, specifier, /*dontRecursivelyResolve*/ true);
17128
17178
if (esModuleSymbol) {
17129
- return createPromiseReturnType(node, getTypeWithSyntheticDefaultImportType(getTypeOfSymbol(esModuleSymbol), esModuleSymbol));
17179
+ return createPromiseReturnType(node, getTypeWithSyntheticDefaultImportType(getTypeOfSymbol(esModuleSymbol), esModuleSymbol, moduleSymbol ));
17130
17180
}
17131
17181
}
17132
17182
return createPromiseReturnType(node, anyType);
17133
17183
}
17134
17184
17135
- function getTypeWithSyntheticDefaultImportType(type: Type, symbol: Symbol): Type {
17185
+ function getTypeWithSyntheticDefaultImportType(type: Type, symbol: Symbol, originalSymbol: Symbol ): Type {
17136
17186
if (allowSyntheticDefaultImports && type && type !== unknownType) {
17137
17187
const synthType = type as SyntheticDefaultModuleType;
17138
17188
if (!synthType.syntheticType) {
17139
- if (!getPropertyOfType(type, InternalSymbolName.Default)) {
17189
+ const hasSyntheticDefault = canHaveSyntheticDefault(forEach(originalSymbol.declarations, sourceFileOrUndefined), originalSymbol, /*dontResolveAlias*/ false);
17190
+ if (hasSyntheticDefault) {
17140
17191
const memberTable = createSymbolTable();
17141
17192
const newSymbol = createSymbol(SymbolFlags.Alias, InternalSymbolName.Default);
17142
17193
newSymbol.target = resolveSymbol(symbol);
17143
17194
memberTable.set(InternalSymbolName.Default, newSymbol);
17144
17195
const anonymousSymbol = createSymbol(SymbolFlags.TypeLiteral, InternalSymbolName.Type);
17145
17196
const defaultContainingObject = createAnonymousType(anonymousSymbol, memberTable, emptyArray, emptyArray, /*stringIndexInfo*/ undefined, /*numberIndexInfo*/ undefined);
17146
17197
anonymousSymbol.type = defaultContainingObject;
17147
- synthType.syntheticType = getIntersectionType([ type, defaultContainingObject]) ;
17198
+ synthType.syntheticType = ( type.flags & TypeFlags.StructuredType && type.symbol.flags & (SymbolFlags.Module | SymbolFlags.Variable)) ? getSpreadType(type , defaultContainingObject, anonymousSymbol, /*propegatedFlags*/ 0) : defaultContainingObject ;
17148
17199
}
17149
17200
else {
17150
17201
synthType.syntheticType = type;
0 commit comments