@@ -7649,11 +7649,9 @@ namespace ts {
7649
7649
if (left.flags & TypeFlags.Any || right.flags & TypeFlags.Any) {
7650
7650
return anyType;
7651
7651
}
7652
- left = filterType(left, t => !(t.flags & TypeFlags.Nullable));
7653
7652
if (left.flags & TypeFlags.Never) {
7654
7653
return right;
7655
7654
}
7656
- right = filterType(right, t => !(t.flags & TypeFlags.Nullable));
7657
7655
if (right.flags & TypeFlags.Never) {
7658
7656
return left;
7659
7657
}
@@ -8373,6 +8371,12 @@ namespace ts {
8373
8371
/**
8374
8372
* This is *not* a bi-directional relationship.
8375
8373
* 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.
8376
8380
*/
8377
8381
function isTypeComparableTo(source: Type, target: Type): boolean {
8378
8382
return isTypeRelatedTo(source, target, comparableRelation);
@@ -8600,6 +8604,7 @@ namespace ts {
8600
8604
8601
8605
function isEmptyObjectType(type: Type): boolean {
8602
8606
return type.flags & TypeFlags.Object ? isEmptyResolvedType(resolveStructuredTypeMembers(<ObjectType>type)) :
8607
+ type.flags & TypeFlags.NonPrimitive ? true :
8603
8608
type.flags & TypeFlags.Union ? forEach((<UnionType>type).types, isEmptyObjectType) :
8604
8609
type.flags & TypeFlags.Intersection ? !forEach((<UnionType>type).types, t => !isEmptyObjectType(t)) :
8605
8610
false;
@@ -15894,7 +15899,7 @@ namespace ts {
15894
15899
const callSignatures = getSignaturesOfType(expressionType, SignatureKind.Call);
15895
15900
if (callSignatures.length) {
15896
15901
const signature = resolveCall(node, callSignatures, candidatesOutArray);
15897
- if (getReturnTypeOfSignature(signature) !== voidType) {
15902
+ if (!isJavaScriptConstructor(signature.declaration) && getReturnTypeOfSignature(signature) !== voidType) {
15898
15903
error(node, Diagnostics.Only_a_void_function_can_be_called_with_the_new_keyword);
15899
15904
}
15900
15905
if (getThisTypeOfSignature(signature) === voidType) {
@@ -16121,10 +16126,30 @@ namespace ts {
16121
16126
return getNodeLinks(node).resolvedSignature === resolvingSignature ? resolvingSignature : getResolvedSignature(node);
16122
16127
}
16123
16128
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
+
16124
16149
function getInferredClassType(symbol: Symbol) {
16125
16150
const links = getSymbolLinks(symbol);
16126
16151
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);
16128
16153
}
16129
16154
return links.inferredClassType;
16130
16155
}
@@ -16164,7 +16189,7 @@ namespace ts {
16164
16189
if (funcSymbol && isDeclarationOfFunctionOrClassExpression(funcSymbol)) {
16165
16190
funcSymbol = getSymbolOfNode((<VariableDeclaration>funcSymbol.valueDeclaration).initializer);
16166
16191
}
16167
- if (funcSymbol && funcSymbol.members && funcSymbol.flags & SymbolFlags.Function ) {
16192
+ if (funcSymbol && funcSymbol.flags & SymbolFlags.Function && ( funcSymbol.members || getJSDocClassTag(funcSymbol.valueDeclaration)) ) {
16168
16193
return getInferredClassType(funcSymbol);
16169
16194
}
16170
16195
else if (noImplicitAny) {
@@ -16182,6 +16207,35 @@ namespace ts {
16182
16207
return getReturnTypeOfSignature(signature);
16183
16208
}
16184
16209
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
+
16185
16239
function isCommonJsRequire(node: Node) {
16186
16240
if (!isRequireCall(node, /*checkArgumentIsStringLiteral*/ true)) {
16187
16241
return false;
@@ -16388,14 +16442,18 @@ namespace ts {
16388
16442
return emptyObjectType;
16389
16443
}
16390
16444
16391
- function createPromiseReturnType(func: FunctionLikeDeclaration, promisedType: Type) {
16445
+ function createPromiseReturnType(func: FunctionLikeDeclaration | ImportCall , promisedType: Type) {
16392
16446
const promiseType = createPromiseType(promisedType);
16393
16447
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);
16395
16451
return unknownType;
16396
16452
}
16397
16453
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);
16399
16457
}
16400
16458
16401
16459
return promiseType;
@@ -17754,6 +17812,10 @@ namespace ts {
17754
17812
case SyntaxKind.ElementAccessExpression:
17755
17813
return checkIndexedAccess(<ElementAccessExpression>node);
17756
17814
case SyntaxKind.CallExpression:
17815
+ if ((<CallExpression>node).expression.kind === SyntaxKind.ImportKeyword) {
17816
+ return checkImportCallExpression(<ImportCall>node);
17817
+ }
17818
+ /* falls through */
17757
17819
case SyntaxKind.NewExpression:
17758
17820
return checkCallExpression(<CallExpression>node);
17759
17821
case SyntaxKind.TaggedTemplateExpression:
@@ -24681,6 +24743,27 @@ namespace ts {
24681
24743
});
24682
24744
return result;
24683
24745
}
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
+ }
24684
24767
}
24685
24768
24686
24769
/** Like 'isDeclarationName', but returns true for LHS of `import { x as y }` or `export { x as y }`. */
0 commit comments