@@ -1471,6 +1471,43 @@ namespace ts {
1471
1471
return getSymbolOfPartOfRightHandSideOfImportEquals(<EntityName>node.moduleReference, dontResolveAlias);
1472
1472
}
1473
1473
1474
+ function resolveExportByName(moduleSymbol: Symbol, name: __String, dontResolveAlias: boolean) {
1475
+ const exportValue = moduleSymbol.exports.get(InternalSymbolName.ExportEquals);
1476
+ return exportValue
1477
+ ? getPropertyOfType(getTypeOfSymbol(exportValue), name)
1478
+ : resolveSymbol(moduleSymbol.exports.get(name), dontResolveAlias);
1479
+ }
1480
+
1481
+ function canHaveSyntheticDefault(file: SourceFile | undefined, moduleSymbol: Symbol, dontResolveAlias: boolean) {
1482
+ if (!allowSyntheticDefaultImports) {
1483
+ return false;
1484
+ }
1485
+ // Declaration files (and ambient modules)
1486
+ if (!file || file.isDeclarationFile) {
1487
+ // Definitely cannot have a synthetic default if they have a default member specified
1488
+ if (resolveExportByName(moduleSymbol, InternalSymbolName.Default, dontResolveAlias)) {
1489
+ return false;
1490
+ }
1491
+ // It _might_ still be incorrect to assume there is no __esModule marker on the import at runtime, even if there is no `default` member
1492
+ // So we check a bit more,
1493
+ if (resolveExportByName(moduleSymbol, escapeLeadingUnderscores("__esModule"), dontResolveAlias)) {
1494
+ // If there is an `__esModule` specified in the declaration (meaning someone explicitly added it or wrote it in their code),
1495
+ // it definitely is a module and does not have a synthetic default
1496
+ return false;
1497
+ }
1498
+ // There are _many_ declaration files not written with esmodules in mind that still get compiled into a format with __esModule set
1499
+ // Meaning there may be no default at runtime - however to be on the permissive side, we allow access to a synthetic default member
1500
+ // as there is no marker to indicate if the accompanying JS has `__esModule` or not, or is even native esm
1501
+ return true;
1502
+ }
1503
+ // TypeScript files never have a synthetic default (as they are always emitted with an __esModule marker) _unless_ they contain an export= statement
1504
+ if (!isSourceFileJavaScript(file)) {
1505
+ return hasExportAssignmentSymbol(moduleSymbol);
1506
+ }
1507
+ // 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
1508
+ return !file.externalModuleIndicator && !resolveExportByName(moduleSymbol, escapeLeadingUnderscores("__esModule"), dontResolveAlias);
1509
+ }
1510
+
1474
1511
function getTargetOfImportClause(node: ImportClause, dontResolveAlias: boolean): Symbol {
1475
1512
const moduleSymbol = resolveExternalModuleName(node, (<ImportDeclaration>node.parent).moduleSpecifier);
1476
1513
@@ -1480,16 +1517,16 @@ namespace ts {
1480
1517
exportDefaultSymbol = moduleSymbol;
1481
1518
}
1482
1519
else {
1483
- const exportValue = moduleSymbol.exports.get("export=" as __String);
1484
- exportDefaultSymbol = exportValue
1485
- ? getPropertyOfType(getTypeOfSymbol(exportValue), InternalSymbolName.Default)
1486
- : resolveSymbol(moduleSymbol.exports.get(InternalSymbolName.Default), dontResolveAlias);
1520
+ exportDefaultSymbol = resolveExportByName(moduleSymbol, InternalSymbolName.Default, dontResolveAlias);
1487
1521
}
1488
1522
1489
- if (!exportDefaultSymbol && !allowSyntheticDefaultImports) {
1523
+ const file = find(moduleSymbol.declarations, isSourceFile);
1524
+ const hasSyntheticDefault = canHaveSyntheticDefault(file, moduleSymbol, dontResolveAlias);
1525
+ if (!exportDefaultSymbol && !hasSyntheticDefault) {
1490
1526
error(node.name, Diagnostics.Module_0_has_no_default_export, symbolToString(moduleSymbol));
1491
1527
}
1492
- else if (!exportDefaultSymbol && allowSyntheticDefaultImports) {
1528
+ else if (!exportDefaultSymbol && hasSyntheticDefault) {
1529
+ // per emit behavior, a synthetic default overrides a "real" .default member if `__esModule` is not present
1493
1530
return resolveExternalModuleSymbol(moduleSymbol, dontResolveAlias) || resolveSymbol(moduleSymbol, dontResolveAlias);
1494
1531
}
1495
1532
return exportDefaultSymbol;
@@ -1889,8 +1926,40 @@ namespace ts {
1889
1926
// combine other declarations with the module or variable (e.g. a class/module, function/module, interface/variable).
1890
1927
function resolveESModuleSymbol(moduleSymbol: Symbol, moduleReferenceExpression: Expression, dontResolveAlias: boolean): Symbol {
1891
1928
const symbol = resolveExternalModuleSymbol(moduleSymbol, dontResolveAlias);
1892
- if (!dontResolveAlias && symbol && !(symbol.flags & (SymbolFlags.Module | SymbolFlags.Variable))) {
1893
- error(moduleReferenceExpression, Diagnostics.Module_0_resolves_to_a_non_module_entity_and_cannot_be_imported_using_this_construct, symbolToString(moduleSymbol));
1929
+ if (!dontResolveAlias && symbol) {
1930
+ if (!(symbol.flags & (SymbolFlags.Module | SymbolFlags.Variable))) {
1931
+ error(moduleReferenceExpression, Diagnostics.Module_0_resolves_to_a_non_module_entity_and_cannot_be_imported_using_this_construct, symbolToString(moduleSymbol));
1932
+ return symbol;
1933
+ }
1934
+ if (compilerOptions.esModuleInterop) {
1935
+ const referenceParent = moduleReferenceExpression.parent;
1936
+ if (
1937
+ (isImportDeclaration(referenceParent) && getNamespaceDeclarationNode(referenceParent)) ||
1938
+ isImportCall(referenceParent)
1939
+ ) {
1940
+ const type = getTypeOfSymbol(symbol);
1941
+ let sigs = getSignaturesOfStructuredType(type, SignatureKind.Call);
1942
+ if (!sigs || !sigs.length) {
1943
+ sigs = getSignaturesOfStructuredType(type, SignatureKind.Construct);
1944
+ }
1945
+ if (sigs && sigs.length) {
1946
+ const moduleType = getTypeWithSyntheticDefaultImportType(type, symbol, moduleSymbol);
1947
+ // Create a new symbol which has the module's type less the call and construct signatures
1948
+ const result = createSymbol(symbol.flags, symbol.escapedName);
1949
+ result.declarations = symbol.declarations ? symbol.declarations.slice() : [];
1950
+ result.parent = symbol.parent;
1951
+ result.target = symbol;
1952
+ result.originatingImport = referenceParent;
1953
+ if (symbol.valueDeclaration) result.valueDeclaration = symbol.valueDeclaration;
1954
+ if (symbol.constEnumOnlyModule) result.constEnumOnlyModule = true;
1955
+ if (symbol.members) result.members = cloneMap(symbol.members);
1956
+ if (symbol.exports) result.exports = cloneMap(symbol.exports);
1957
+ const resolvedModuleType = resolveStructuredTypeMembers(moduleType as StructuredType); // Should already be resolved from the signature checks above
1958
+ result.type = createAnonymousType(result, resolvedModuleType.members, emptyArray, emptyArray, resolvedModuleType.stringIndexInfo, resolvedModuleType.numberIndexInfo);
1959
+ return result;
1960
+ }
1961
+ }
1962
+ }
1894
1963
}
1895
1964
return symbol;
1896
1965
}
@@ -9452,6 +9521,17 @@ namespace ts {
9452
9521
9453
9522
diagnostics.add(createDiagnosticForNodeFromMessageChain(errorNode, errorInfo));
9454
9523
}
9524
+ // Check if we should issue an extra diagnostic to produce a quickfix for a slightly incorrect import statement
9525
+ if (headMessage && errorNode && !result && source.symbol) {
9526
+ const links = getSymbolLinks(source.symbol);
9527
+ if (links.originatingImport && !isImportCall(links.originatingImport)) {
9528
+ const helpfulRetry = checkTypeRelatedTo(getTypeOfSymbol(links.target), target, relation, /*errorNode*/ undefined);
9529
+ if (helpfulRetry) {
9530
+ // Likely an incorrect import. Issue a helpful diagnostic to produce a quickfix to change the import
9531
+ diagnostics.add(createDiagnosticForNode(links.originatingImport, Diagnostics.A_namespace_style_import_cannot_be_called_or_constructed_and_will_cause_a_failure_at_runtime));
9532
+ }
9533
+ }
9534
+ }
9455
9535
return result !== Ternary.False;
9456
9536
9457
9537
function reportError(message: DiagnosticMessage, arg0?: string, arg1?: string, arg2?: string): void {
@@ -17320,7 +17400,7 @@ namespace ts {
17320
17400
error(node, Diagnostics.Value_of_type_0_is_not_callable_Did_you_mean_to_include_new, typeToString(funcType));
17321
17401
}
17322
17402
else {
17323
- error (node, Diagnostics.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures, typeToString(apparentType) );
17403
+ invocationError (node, apparentType, SignatureKind.Call );
17324
17404
}
17325
17405
return resolveErrorCall(node);
17326
17406
}
@@ -17410,7 +17490,7 @@ namespace ts {
17410
17490
return signature;
17411
17491
}
17412
17492
17413
- error (node, Diagnostics.Cannot_use_new_with_an_expression_whose_type_lacks_a_call_or_construct_signature );
17493
+ invocationError (node, expressionType, SignatureKind.Construct );
17414
17494
return resolveErrorCall(node);
17415
17495
}
17416
17496
@@ -17457,6 +17537,28 @@ namespace ts {
17457
17537
return true;
17458
17538
}
17459
17539
17540
+ function invocationError(node: Node, apparentType: Type, kind: SignatureKind) {
17541
+ error(node, kind === SignatureKind.Call
17542
+ ? Diagnostics.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures
17543
+ : Diagnostics.Cannot_use_new_with_an_expression_whose_type_lacks_a_call_or_construct_signature
17544
+ , typeToString(apparentType));
17545
+ invocationErrorRecovery(apparentType, kind);
17546
+ }
17547
+
17548
+ function invocationErrorRecovery(apparentType: Type, kind: SignatureKind) {
17549
+ if (!apparentType.symbol) {
17550
+ return;
17551
+ }
17552
+ const importNode = getSymbolLinks(apparentType.symbol).originatingImport;
17553
+ // Create a diagnostic on the originating import if possible onto which we can attach a quickfix
17554
+ // 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
17555
+ if (importNode && !isImportCall(importNode)) {
17556
+ const sigs = getSignaturesOfType(getTypeOfSymbol(getSymbolLinks(apparentType.symbol).target), kind);
17557
+ if (!sigs || !sigs.length) return;
17558
+ error(importNode, Diagnostics.A_namespace_style_import_cannot_be_called_or_constructed_and_will_cause_a_failure_at_runtime);
17559
+ }
17560
+ }
17561
+
17460
17562
function resolveTaggedTemplateExpression(node: TaggedTemplateExpression, candidatesOutArray: Signature[]): Signature {
17461
17563
const tagType = checkExpression(node.tag);
17462
17564
const apparentType = getApparentType(tagType);
@@ -17474,7 +17576,7 @@ namespace ts {
17474
17576
}
17475
17577
17476
17578
if (!callSignatures.length) {
17477
- error (node, Diagnostics.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures, typeToString(apparentType) );
17579
+ invocationError (node, apparentType, SignatureKind.Call );
17478
17580
return resolveErrorCall(node);
17479
17581
}
17480
17582
@@ -17531,6 +17633,7 @@ namespace ts {
17531
17633
errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures, typeToString(apparentType));
17532
17634
errorInfo = chainDiagnosticMessages(errorInfo, headMessage);
17533
17635
diagnostics.add(createDiagnosticForNodeFromMessageChain(node, errorInfo));
17636
+ invocationErrorRecovery(apparentType, SignatureKind.Call);
17534
17637
return resolveErrorCall(node);
17535
17638
}
17536
17639
@@ -17785,25 +17888,27 @@ namespace ts {
17785
17888
if (moduleSymbol) {
17786
17889
const esModuleSymbol = resolveESModuleSymbol(moduleSymbol, specifier, /*dontRecursivelyResolve*/ true);
17787
17890
if (esModuleSymbol) {
17788
- return createPromiseReturnType(node, getTypeWithSyntheticDefaultImportType(getTypeOfSymbol(esModuleSymbol), esModuleSymbol));
17891
+ return createPromiseReturnType(node, getTypeWithSyntheticDefaultImportType(getTypeOfSymbol(esModuleSymbol), esModuleSymbol, moduleSymbol ));
17789
17892
}
17790
17893
}
17791
17894
return createPromiseReturnType(node, anyType);
17792
17895
}
17793
17896
17794
- function getTypeWithSyntheticDefaultImportType(type: Type, symbol: Symbol): Type {
17897
+ function getTypeWithSyntheticDefaultImportType(type: Type, symbol: Symbol, originalSymbol: Symbol ): Type {
17795
17898
if (allowSyntheticDefaultImports && type && type !== unknownType) {
17796
17899
const synthType = type as SyntheticDefaultModuleType;
17797
17900
if (!synthType.syntheticType) {
17798
- if (!getPropertyOfType(type, InternalSymbolName.Default)) {
17901
+ const file = find(originalSymbol.declarations, isSourceFile);
17902
+ const hasSyntheticDefault = canHaveSyntheticDefault(file, originalSymbol, /*dontResolveAlias*/ false);
17903
+ if (hasSyntheticDefault) {
17799
17904
const memberTable = createSymbolTable();
17800
17905
const newSymbol = createSymbol(SymbolFlags.Alias, InternalSymbolName.Default);
17801
17906
newSymbol.target = resolveSymbol(symbol);
17802
17907
memberTable.set(InternalSymbolName.Default, newSymbol);
17803
17908
const anonymousSymbol = createSymbol(SymbolFlags.TypeLiteral, InternalSymbolName.Type);
17804
17909
const defaultContainingObject = createAnonymousType(anonymousSymbol, memberTable, emptyArray, emptyArray, /*stringIndexInfo*/ undefined, /*numberIndexInfo*/ undefined);
17805
17910
anonymousSymbol.type = defaultContainingObject;
17806
- synthType.syntheticType = getIntersectionType([ type, defaultContainingObject]) ;
17911
+ synthType.syntheticType = ( type.flags & TypeFlags.StructuredType && type.symbol.flags & (SymbolFlags.Module | SymbolFlags.Variable)) ? getSpreadType(type , defaultContainingObject, anonymousSymbol, /*propegatedFlags*/ 0) : defaultContainingObject ;
17807
17912
}
17808
17913
else {
17809
17914
synthType.syntheticType = type;
0 commit comments