@@ -7649,11 +7649,9 @@ namespace ts {
76497649 if (left.flags & TypeFlags.Any || right.flags & TypeFlags.Any) {
76507650 return anyType;
76517651 }
7652- left = filterType(left, t => !(t.flags & TypeFlags.Nullable));
76537652 if (left.flags & TypeFlags.Never) {
76547653 return right;
76557654 }
7656- right = filterType(right, t => !(t.flags & TypeFlags.Nullable));
76577655 if (right.flags & TypeFlags.Never) {
76587656 return left;
76597657 }
@@ -8373,6 +8371,12 @@ namespace ts {
83738371 /**
83748372 * This is *not* a bi-directional relationship.
83758373 * If one needs to check both directions for comparability, use a second call to this function or 'checkTypeComparableTo'.
8374+ *
8375+ * A type S is comparable to a type T if some (but not necessarily all) of the possible values of S are also possible values of T.
8376+ * It is used to check following cases:
8377+ * - the types of the left and right sides of equality/inequality operators (`===`, `!==`, `==`, `!=`).
8378+ * - the types of `case` clause expressions and their respective `switch` expressions.
8379+ * - the type of an expression in a type assertion with the type being asserted.
83768380 */
83778381 function isTypeComparableTo(source: Type, target: Type): boolean {
83788382 return isTypeRelatedTo(source, target, comparableRelation);
@@ -8600,6 +8604,7 @@ namespace ts {
86008604
86018605 function isEmptyObjectType(type: Type): boolean {
86028606 return type.flags & TypeFlags.Object ? isEmptyResolvedType(resolveStructuredTypeMembers(<ObjectType>type)) :
8607+ type.flags & TypeFlags.NonPrimitive ? true :
86038608 type.flags & TypeFlags.Union ? forEach((<UnionType>type).types, isEmptyObjectType) :
86048609 type.flags & TypeFlags.Intersection ? !forEach((<UnionType>type).types, t => !isEmptyObjectType(t)) :
86058610 false;
@@ -15894,7 +15899,7 @@ namespace ts {
1589415899 const callSignatures = getSignaturesOfType(expressionType, SignatureKind.Call);
1589515900 if (callSignatures.length) {
1589615901 const signature = resolveCall(node, callSignatures, candidatesOutArray);
15897- if (getReturnTypeOfSignature(signature) !== voidType) {
15902+ if (!isJavaScriptConstructor(signature.declaration) && getReturnTypeOfSignature(signature) !== voidType) {
1589815903 error(node, Diagnostics.Only_a_void_function_can_be_called_with_the_new_keyword);
1589915904 }
1590015905 if (getThisTypeOfSignature(signature) === voidType) {
@@ -16121,10 +16126,30 @@ namespace ts {
1612116126 return getNodeLinks(node).resolvedSignature === resolvingSignature ? resolvingSignature : getResolvedSignature(node);
1612216127 }
1612316128
16129+ /**
16130+ * Indicates whether a declaration can be treated as a constructor in a JavaScript
16131+ * file.
16132+ */
16133+ function isJavaScriptConstructor(node: Declaration): boolean {
16134+ if (isInJavaScriptFile(node)) {
16135+ // If the node has a @class tag, treat it like a constructor.
16136+ if (getJSDocClassTag(node)) return true;
16137+
16138+ // If the symbol of the node has members, treat it like a constructor.
16139+ const symbol = isFunctionDeclaration(node) || isFunctionExpression(node) ? getSymbolOfNode(node) :
16140+ isVariableDeclaration(node) && isFunctionExpression(node.initializer) ? getSymbolOfNode(node.initializer) :
16141+ undefined;
16142+
16143+ return symbol && symbol.members !== undefined;
16144+ }
16145+
16146+ return false;
16147+ }
16148+
1612416149 function getInferredClassType(symbol: Symbol) {
1612516150 const links = getSymbolLinks(symbol);
1612616151 if (!links.inferredClassType) {
16127- links.inferredClassType = createAnonymousType(symbol, symbol.members, emptyArray, emptyArray, /*stringIndexType*/ undefined, /*numberIndexType*/ undefined);
16152+ links.inferredClassType = createAnonymousType(symbol, symbol.members || emptySymbols , emptyArray, emptyArray, /*stringIndexType*/ undefined, /*numberIndexType*/ undefined);
1612816153 }
1612916154 return links.inferredClassType;
1613016155 }
@@ -16164,7 +16189,7 @@ namespace ts {
1616416189 if (funcSymbol && isDeclarationOfFunctionOrClassExpression(funcSymbol)) {
1616516190 funcSymbol = getSymbolOfNode((<VariableDeclaration>funcSymbol.valueDeclaration).initializer);
1616616191 }
16167- if (funcSymbol && funcSymbol.members && funcSymbol.flags & SymbolFlags.Function ) {
16192+ if (funcSymbol && funcSymbol.flags & SymbolFlags.Function && ( funcSymbol.members || getJSDocClassTag(funcSymbol.valueDeclaration)) ) {
1616816193 return getInferredClassType(funcSymbol);
1616916194 }
1617016195 else if (noImplicitAny) {
@@ -16182,6 +16207,35 @@ namespace ts {
1618216207 return getReturnTypeOfSignature(signature);
1618316208 }
1618416209
16210+ function checkImportCallExpression(node: ImportCall): Type {
16211+ // Check grammar of dynamic import
16212+ checkGrammarArguments(node, node.arguments) || checkGrammarImportCallExpression(node);
16213+
16214+ if (node.arguments.length === 0) {
16215+ return createPromiseReturnType(node, anyType);
16216+ }
16217+ const specifier = node.arguments[0];
16218+ const specifierType = checkExpressionCached(specifier);
16219+ // Even though multiple arugments is grammatically incorrect, type-check extra arguments for completion
16220+ for (let i = 1; i < node.arguments.length; ++i) {
16221+ checkExpressionCached(node.arguments[i]);
16222+ }
16223+
16224+ if (specifierType.flags & TypeFlags.Undefined || specifierType.flags & TypeFlags.Null || !isTypeAssignableTo(specifierType, stringType)) {
16225+ error(specifier, Diagnostics.Dynamic_import_s_specifier_must_be_of_type_string_but_here_has_type_0, typeToString(specifierType));
16226+ }
16227+
16228+ // resolveExternalModuleName will return undefined if the moduleReferenceExpression is not a string literal
16229+ const moduleSymbol = resolveExternalModuleName(node, specifier);
16230+ if (moduleSymbol) {
16231+ const esModuleSymbol = resolveESModuleSymbol(moduleSymbol, specifier, /*dontRecursivelyResolve*/ true);
16232+ if (esModuleSymbol) {
16233+ return createPromiseReturnType(node, getTypeOfSymbol(esModuleSymbol));
16234+ }
16235+ }
16236+ return createPromiseReturnType(node, anyType);
16237+ }
16238+
1618516239 function isCommonJsRequire(node: Node) {
1618616240 if (!isRequireCall(node, /*checkArgumentIsStringLiteral*/ true)) {
1618716241 return false;
@@ -16388,14 +16442,18 @@ namespace ts {
1638816442 return emptyObjectType;
1638916443 }
1639016444
16391- function createPromiseReturnType(func: FunctionLikeDeclaration, promisedType: Type) {
16445+ function createPromiseReturnType(func: FunctionLikeDeclaration | ImportCall , promisedType: Type) {
1639216446 const promiseType = createPromiseType(promisedType);
1639316447 if (promiseType === emptyObjectType) {
16394- error(func, Diagnostics.An_async_function_or_method_must_return_a_Promise_Make_sure_you_have_a_declaration_for_Promise_or_include_ES2015_in_your_lib_option);
16448+ error(func, isImportCall(func) ?
16449+ Diagnostics.A_dynamic_import_call_returns_a_Promise_Make_sure_you_have_a_declaration_for_Promise_or_include_ES2015_in_your_lib_option :
16450+ Diagnostics.An_async_function_or_method_must_return_a_Promise_Make_sure_you_have_a_declaration_for_Promise_or_include_ES2015_in_your_lib_option);
1639516451 return unknownType;
1639616452 }
1639716453 else if (!getGlobalPromiseConstructorSymbol(/*reportErrors*/ true)) {
16398- error(func, Diagnostics.An_async_function_or_method_in_ES5_SlashES3_requires_the_Promise_constructor_Make_sure_you_have_a_declaration_for_the_Promise_constructor_or_include_ES2015_in_your_lib_option);
16454+ error(func, isImportCall(func) ?
16455+ Diagnostics.A_dynamic_import_call_in_ES5_SlashES3_requires_the_Promise_constructor_Make_sure_you_have_a_declaration_for_the_Promise_constructor_or_include_ES2015_in_your_lib_option :
16456+ Diagnostics.An_async_function_or_method_in_ES5_SlashES3_requires_the_Promise_constructor_Make_sure_you_have_a_declaration_for_the_Promise_constructor_or_include_ES2015_in_your_lib_option);
1639916457 }
1640016458
1640116459 return promiseType;
@@ -17754,6 +17812,10 @@ namespace ts {
1775417812 case SyntaxKind.ElementAccessExpression:
1775517813 return checkIndexedAccess(<ElementAccessExpression>node);
1775617814 case SyntaxKind.CallExpression:
17815+ if ((<CallExpression>node).expression.kind === SyntaxKind.ImportKeyword) {
17816+ return checkImportCallExpression(<ImportCall>node);
17817+ }
17818+ /* falls through */
1775717819 case SyntaxKind.NewExpression:
1775817820 return checkCallExpression(<CallExpression>node);
1775917821 case SyntaxKind.TaggedTemplateExpression:
@@ -24681,6 +24743,27 @@ namespace ts {
2468124743 });
2468224744 return result;
2468324745 }
24746+
24747+ function checkGrammarImportCallExpression(node: ImportCall): boolean {
24748+ if (modulekind === ModuleKind.ES2015) {
24749+ return grammarErrorOnNode(node, Diagnostics.Dynamic_import_cannot_be_used_when_targeting_ECMAScript_2015_modules);
24750+ }
24751+
24752+ if (node.typeArguments) {
24753+ return grammarErrorOnNode(node, Diagnostics.Dynamic_import_cannot_have_type_arguments);
24754+ }
24755+
24756+ const arguments = node.arguments;
24757+ if (arguments.length !== 1) {
24758+ return grammarErrorOnNode(node, Diagnostics.Dynamic_import_must_have_one_specifier_as_an_argument);
24759+ }
24760+
24761+ // see: parseArgumentOrArrayLiteralElement...we use this function which parse arguments of callExpression to parse specifier for dynamic import.
24762+ // parseArgumentOrArrayLiteralElement allows spread element to be in an argument list which is not allowed as specifier in dynamic import.
24763+ if (isSpreadElement(arguments[0])) {
24764+ return grammarErrorOnNode(arguments[0], Diagnostics.Specifier_of_dynamic_import_cannot_be_spread_element);
24765+ }
24766+ }
2468424767 }
2468524768
2468624769 /** Like 'isDeclarationName', but returns true for LHS of `import { x as y }` or `export { x as y }`. */
0 commit comments