@@ -8975,7 +8975,7 @@ namespace ts {
8975
8975
8976
8976
function getTypeWithDefault(type: Type, defaultExpression: Expression) {
8977
8977
if (defaultExpression) {
8978
- const defaultType = checkExpression (defaultExpression);
8978
+ const defaultType = getTypeOfExpression (defaultExpression);
8979
8979
return getUnionType([getTypeWithFacts(type, TypeFacts.NEUndefined), defaultType]);
8980
8980
}
8981
8981
return type;
@@ -9002,7 +9002,7 @@ namespace ts {
9002
9002
function getAssignedTypeOfBinaryExpression(node: BinaryExpression): Type {
9003
9003
return node.parent.kind === SyntaxKind.ArrayLiteralExpression || node.parent.kind === SyntaxKind.PropertyAssignment ?
9004
9004
getTypeWithDefault(getAssignedType(node), node.right) :
9005
- checkExpression (node.right);
9005
+ getTypeOfExpression (node.right);
9006
9006
}
9007
9007
9008
9008
function getAssignedTypeOfArrayLiteralElement(node: ArrayLiteralExpression, element: Expression): Type {
@@ -9060,7 +9060,7 @@ namespace ts {
9060
9060
// from its initializer, we'll already have cached the type. Otherwise we compute it now
9061
9061
// without caching such that transient types are reflected.
9062
9062
const links = getNodeLinks(node);
9063
- return links.resolvedType || checkExpression (node);
9063
+ return links.resolvedType || getTypeOfExpression (node);
9064
9064
}
9065
9065
9066
9066
function getInitialTypeOfVariableDeclaration(node: VariableDeclaration) {
@@ -9120,7 +9120,7 @@ namespace ts {
9120
9120
9121
9121
function getTypeOfSwitchClause(clause: CaseClause | DefaultClause) {
9122
9122
if (clause.kind === SyntaxKind.CaseClause) {
9123
- const caseType = getRegularTypeOfLiteralType(checkExpression ((<CaseClause>clause).expression));
9123
+ const caseType = getRegularTypeOfLiteralType(getTypeOfExpression ((<CaseClause>clause).expression));
9124
9124
return isUnitType(caseType) ? caseType : undefined;
9125
9125
}
9126
9126
return neverType;
@@ -9225,7 +9225,7 @@ namespace ts {
9225
9225
// we defer subtype reduction until the evolving array type is finalized into a manifest
9226
9226
// array type.
9227
9227
function addEvolvingArrayElementType(evolvingArrayType: EvolvingArrayType, node: Expression): EvolvingArrayType {
9228
- const elementType = getBaseTypeOfLiteralType(checkExpression (node));
9228
+ const elementType = getBaseTypeOfLiteralType(getTypeOfExpression (node));
9229
9229
return isTypeSubsetOf(elementType, evolvingArrayType.elementType) ? evolvingArrayType : getEvolvingArrayType(getUnionType([evolvingArrayType.elementType, elementType]));
9230
9230
}
9231
9231
@@ -9286,7 +9286,7 @@ namespace ts {
9286
9286
(<BinaryExpression>parent.parent).operatorToken.kind === SyntaxKind.EqualsToken &&
9287
9287
(<BinaryExpression>parent.parent).left === parent &&
9288
9288
!isAssignmentTarget(parent.parent) &&
9289
- isTypeAnyOrAllConstituentTypesHaveKind(checkExpression ((<ElementAccessExpression>parent).argumentExpression), TypeFlags.NumberLike | TypeFlags.Undefined);
9289
+ isTypeAnyOrAllConstituentTypesHaveKind(getTypeOfExpression ((<ElementAccessExpression>parent).argumentExpression), TypeFlags.NumberLike | TypeFlags.Undefined);
9290
9290
return isLengthPushOrUnshift || isElementAssignment;
9291
9291
}
9292
9292
@@ -9448,7 +9448,7 @@ namespace ts {
9448
9448
}
9449
9449
}
9450
9450
else {
9451
- const indexType = checkExpression ((<ElementAccessExpression>(<BinaryExpression>node).left).argumentExpression);
9451
+ const indexType = getTypeOfExpression ((<ElementAccessExpression>(<BinaryExpression>node).left).argumentExpression);
9452
9452
if (isTypeAnyOrAllConstituentTypesHaveKind(indexType, TypeFlags.NumberLike | TypeFlags.Undefined)) {
9453
9453
evolvedType = addEvolvingArrayElementType(evolvedType, (<BinaryExpression>node).right);
9454
9454
}
@@ -9673,7 +9673,7 @@ namespace ts {
9673
9673
if (operator === SyntaxKind.ExclamationEqualsToken || operator === SyntaxKind.ExclamationEqualsEqualsToken) {
9674
9674
assumeTrue = !assumeTrue;
9675
9675
}
9676
- const valueType = checkExpression (value);
9676
+ const valueType = getTypeOfExpression (value);
9677
9677
if (valueType.flags & TypeFlags.Nullable) {
9678
9678
if (!strictNullChecks) {
9679
9679
return type;
@@ -9760,7 +9760,7 @@ namespace ts {
9760
9760
}
9761
9761
9762
9762
// Check that right operand is a function type with a prototype property
9763
- const rightType = checkExpression (expr.right);
9763
+ const rightType = getTypeOfExpression (expr.right);
9764
9764
if (!isTypeSubtypeOf(rightType, globalFunctionType)) {
9765
9765
return type;
9766
9766
}
@@ -9901,7 +9901,7 @@ namespace ts {
9901
9901
location = location.parent;
9902
9902
}
9903
9903
if (isPartOfExpression(location) && !isAssignmentTarget(location)) {
9904
- const type = checkExpression (<Expression>location);
9904
+ const type = getTypeOfExpression (<Expression>location);
9905
9905
if (getExportSymbolOfValueSymbolIfExported(getNodeLinks(location).resolvedSymbol) === symbol) {
9906
9906
return type;
9907
9907
}
@@ -10769,15 +10769,15 @@ namespace ts {
10769
10769
10770
10770
// In an assignment expression, the right operand is contextually typed by the type of the left operand.
10771
10771
if (node === binaryExpression.right) {
10772
- return checkExpression (binaryExpression.left);
10772
+ return getTypeOfExpression (binaryExpression.left);
10773
10773
}
10774
10774
}
10775
10775
else if (operator === SyntaxKind.BarBarToken) {
10776
10776
// When an || expression has a contextual type, the operands are contextually typed by that type. When an ||
10777
10777
// expression has no contextual type, the right operand is contextually typed by the type of the left operand.
10778
10778
let type = getContextualType(binaryExpression);
10779
10779
if (!type && node === binaryExpression.right) {
10780
- type = checkExpression (binaryExpression.left);
10780
+ type = getTypeOfExpression (binaryExpression.left);
10781
10781
}
10782
10782
return type;
10783
10783
}
@@ -12148,7 +12148,7 @@ namespace ts {
12148
12148
if (node.kind === SyntaxKind.ForInStatement &&
12149
12149
child === (<ForInStatement>node).statement &&
12150
12150
getForInVariableSymbol(<ForInStatement>node) === symbol &&
12151
- hasNumericPropertyNames(checkExpression ((<ForInStatement>node).expression))) {
12151
+ hasNumericPropertyNames(getTypeOfExpression ((<ForInStatement>node).expression))) {
12152
12152
return true;
12153
12153
}
12154
12154
child = node;
@@ -13784,7 +13784,7 @@ namespace ts {
13784
13784
if (!node.possiblyExhaustive) {
13785
13785
return false;
13786
13786
}
13787
- const type = checkExpression (node.expression);
13787
+ const type = getTypeOfExpression (node.expression);
13788
13788
if (!isLiteralType(type)) {
13789
13789
return false;
13790
13790
}
@@ -14876,6 +14876,24 @@ namespace ts {
14876
14876
return type;
14877
14877
}
14878
14878
14879
+ // Returns the type of an expression. Unlike checkExpression, this function is simply concerned
14880
+ // with computing the type and may not fully check all contained sub-expressions for errors.
14881
+ function getTypeOfExpression(node: Expression) {
14882
+ // Optimize for the common case of a call to a function with a single non-generic call
14883
+ // signature where we can just fetch the return type without checking the arguments.
14884
+ if (node.kind === SyntaxKind.CallExpression && (<CallExpression>node).expression.kind !== SyntaxKind.SuperKeyword) {
14885
+ const funcType = checkNonNullExpression((<CallExpression>node).expression);
14886
+ const signature = getSingleCallSignature(funcType);
14887
+ if (signature && !signature.typeParameters) {
14888
+ return getReturnTypeOfSignature(signature);
14889
+ }
14890
+ }
14891
+ // Otherwise simply call checkExpression. Ideally, the entire family of checkXXX functions
14892
+ // should have a parameter that indicates whether full error checking is required such that
14893
+ // we can perform the optimizations locally.
14894
+ return checkExpression(node);
14895
+ }
14896
+
14879
14897
// Checks an expression and returns its type. The contextualMapper parameter serves two purposes: When
14880
14898
// contextualMapper is not undefined and not equal to the identityMapper function object it indicates that the
14881
14899
// expression is being inferentially typed (section 4.15.2 in spec) and provides the type mapper to use in
@@ -18258,7 +18276,7 @@ namespace ts {
18258
18276
}
18259
18277
}
18260
18278
18261
- enumType = checkExpression (expression);
18279
+ enumType = getTypeOfExpression (expression);
18262
18280
// allow references to constant members of other enums
18263
18281
if (!(enumType.symbol && (enumType.symbol.flags & SymbolFlags.Enum))) {
18264
18282
return undefined;
@@ -19428,7 +19446,7 @@ namespace ts {
19428
19446
// fallthrough
19429
19447
19430
19448
case SyntaxKind.SuperKeyword:
19431
- const type = isPartOfExpression(node) ? checkExpression (<Expression>node) : getTypeFromTypeNode(<TypeNode>node);
19449
+ const type = isPartOfExpression(node) ? getTypeOfExpression (<Expression>node) : getTypeFromTypeNode(<TypeNode>node);
19432
19450
return type.symbol;
19433
19451
19434
19452
case SyntaxKind.ThisType:
@@ -19458,7 +19476,7 @@ namespace ts {
19458
19476
case SyntaxKind.NumericLiteral:
19459
19477
// index access
19460
19478
if (node.parent.kind === SyntaxKind.ElementAccessExpression && (<ElementAccessExpression>node.parent).argumentExpression === node) {
19461
- const objectType = checkExpression ((<ElementAccessExpression>node.parent).expression);
19479
+ const objectType = getTypeOfExpression ((<ElementAccessExpression>node.parent).expression);
19462
19480
if (objectType === unknownType) return undefined;
19463
19481
const apparentType = getApparentType(objectType);
19464
19482
if (apparentType === unknownType) return undefined;
@@ -19497,7 +19515,7 @@ namespace ts {
19497
19515
}
19498
19516
19499
19517
if (isPartOfExpression(node)) {
19500
- return getTypeOfExpression (<Expression>node);
19518
+ return getRegularTypeOfExpression (<Expression>node);
19501
19519
}
19502
19520
19503
19521
if (isExpressionWithTypeArgumentsInClassExtendsClause(node)) {
@@ -19559,7 +19577,7 @@ namespace ts {
19559
19577
// If this is from "for" initializer
19560
19578
// for ({a } = elems[0];.....) { }
19561
19579
if (expr.parent.kind === SyntaxKind.BinaryExpression) {
19562
- const iteratedType = checkExpression ((<BinaryExpression>expr.parent).right);
19580
+ const iteratedType = getTypeOfExpression ((<BinaryExpression>expr.parent).right);
19563
19581
return checkDestructuringAssignment(expr, iteratedType || unknownType);
19564
19582
}
19565
19583
// If this is from nested object binding pattern
@@ -19589,11 +19607,11 @@ namespace ts {
19589
19607
return typeOfObjectLiteral && getPropertyOfType(typeOfObjectLiteral, location.text);
19590
19608
}
19591
19609
19592
- function getTypeOfExpression (expr: Expression): Type {
19610
+ function getRegularTypeOfExpression (expr: Expression): Type {
19593
19611
if (isRightSideOfQualifiedNameOrPropertyAccess(expr)) {
19594
19612
expr = <Expression>expr.parent;
19595
19613
}
19596
- return getRegularTypeOfLiteralType(checkExpression (expr));
19614
+ return getRegularTypeOfLiteralType(getTypeOfExpression (expr));
19597
19615
}
19598
19616
19599
19617
/**
@@ -20020,7 +20038,7 @@ namespace ts {
20020
20038
}
20021
20039
20022
20040
function writeTypeOfExpression(expr: Expression, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter) {
20023
- const type = getWidenedType(getTypeOfExpression (expr));
20041
+ const type = getWidenedType(getRegularTypeOfExpression (expr));
20024
20042
getSymbolDisplayBuilder().buildTypeDisplay(type, writer, enclosingDeclaration, flags);
20025
20043
}
20026
20044
0 commit comments