@@ -9000,7 +9000,7 @@ namespace ts {
9000
9000
9001
9001
function getTypeWithDefault(type: Type, defaultExpression: Expression) {
9002
9002
if (defaultExpression) {
9003
- const defaultType = checkExpression (defaultExpression);
9003
+ const defaultType = getTypeOfExpression (defaultExpression);
9004
9004
return getUnionType([getTypeWithFacts(type, TypeFacts.NEUndefined), defaultType]);
9005
9005
}
9006
9006
return type;
@@ -9027,7 +9027,7 @@ namespace ts {
9027
9027
function getAssignedTypeOfBinaryExpression(node: BinaryExpression): Type {
9028
9028
return node.parent.kind === SyntaxKind.ArrayLiteralExpression || node.parent.kind === SyntaxKind.PropertyAssignment ?
9029
9029
getTypeWithDefault(getAssignedType(node), node.right) :
9030
- checkExpression (node.right);
9030
+ getTypeOfExpression (node.right);
9031
9031
}
9032
9032
9033
9033
function getAssignedTypeOfArrayLiteralElement(node: ArrayLiteralExpression, element: Expression): Type {
@@ -9085,7 +9085,7 @@ namespace ts {
9085
9085
// from its initializer, we'll already have cached the type. Otherwise we compute it now
9086
9086
// without caching such that transient types are reflected.
9087
9087
const links = getNodeLinks(node);
9088
- return links.resolvedType || checkExpression (node);
9088
+ return links.resolvedType || getTypeOfExpression (node);
9089
9089
}
9090
9090
9091
9091
function getInitialTypeOfVariableDeclaration(node: VariableDeclaration) {
@@ -9145,7 +9145,7 @@ namespace ts {
9145
9145
9146
9146
function getTypeOfSwitchClause(clause: CaseClause | DefaultClause) {
9147
9147
if (clause.kind === SyntaxKind.CaseClause) {
9148
- const caseType = getRegularTypeOfLiteralType(checkExpression ((<CaseClause>clause).expression));
9148
+ const caseType = getRegularTypeOfLiteralType(getTypeOfExpression ((<CaseClause>clause).expression));
9149
9149
return isUnitType(caseType) ? caseType : undefined;
9150
9150
}
9151
9151
return neverType;
@@ -9250,7 +9250,7 @@ namespace ts {
9250
9250
// we defer subtype reduction until the evolving array type is finalized into a manifest
9251
9251
// array type.
9252
9252
function addEvolvingArrayElementType(evolvingArrayType: EvolvingArrayType, node: Expression): EvolvingArrayType {
9253
- const elementType = getBaseTypeOfLiteralType(checkExpression (node));
9253
+ const elementType = getBaseTypeOfLiteralType(getTypeOfExpression (node));
9254
9254
return isTypeSubsetOf(elementType, evolvingArrayType.elementType) ? evolvingArrayType : getEvolvingArrayType(getUnionType([evolvingArrayType.elementType, elementType]));
9255
9255
}
9256
9256
@@ -9311,7 +9311,7 @@ namespace ts {
9311
9311
(<BinaryExpression>parent.parent).operatorToken.kind === SyntaxKind.EqualsToken &&
9312
9312
(<BinaryExpression>parent.parent).left === parent &&
9313
9313
!isAssignmentTarget(parent.parent) &&
9314
- isTypeAnyOrAllConstituentTypesHaveKind(checkExpression ((<ElementAccessExpression>parent).argumentExpression), TypeFlags.NumberLike | TypeFlags.Undefined);
9314
+ isTypeAnyOrAllConstituentTypesHaveKind(getTypeOfExpression ((<ElementAccessExpression>parent).argumentExpression), TypeFlags.NumberLike | TypeFlags.Undefined);
9315
9315
return isLengthPushOrUnshift || isElementAssignment;
9316
9316
}
9317
9317
@@ -9473,7 +9473,7 @@ namespace ts {
9473
9473
}
9474
9474
}
9475
9475
else {
9476
- const indexType = checkExpression ((<ElementAccessExpression>(<BinaryExpression>node).left).argumentExpression);
9476
+ const indexType = getTypeOfExpression ((<ElementAccessExpression>(<BinaryExpression>node).left).argumentExpression);
9477
9477
if (isTypeAnyOrAllConstituentTypesHaveKind(indexType, TypeFlags.NumberLike | TypeFlags.Undefined)) {
9478
9478
evolvedType = addEvolvingArrayElementType(evolvedType, (<BinaryExpression>node).right);
9479
9479
}
@@ -9698,7 +9698,7 @@ namespace ts {
9698
9698
if (operator === SyntaxKind.ExclamationEqualsToken || operator === SyntaxKind.ExclamationEqualsEqualsToken) {
9699
9699
assumeTrue = !assumeTrue;
9700
9700
}
9701
- const valueType = checkExpression (value);
9701
+ const valueType = getTypeOfExpression (value);
9702
9702
if (valueType.flags & TypeFlags.Nullable) {
9703
9703
if (!strictNullChecks) {
9704
9704
return type;
@@ -9785,7 +9785,7 @@ namespace ts {
9785
9785
}
9786
9786
9787
9787
// Check that right operand is a function type with a prototype property
9788
- const rightType = checkExpression (expr.right);
9788
+ const rightType = getTypeOfExpression (expr.right);
9789
9789
if (!isTypeSubtypeOf(rightType, globalFunctionType)) {
9790
9790
return type;
9791
9791
}
@@ -9926,7 +9926,7 @@ namespace ts {
9926
9926
location = location.parent;
9927
9927
}
9928
9928
if (isPartOfExpression(location) && !isAssignmentTarget(location)) {
9929
- const type = checkExpression (<Expression>location);
9929
+ const type = getTypeOfExpression (<Expression>location);
9930
9930
if (getExportSymbolOfValueSymbolIfExported(getNodeLinks(location).resolvedSymbol) === symbol) {
9931
9931
return type;
9932
9932
}
@@ -10794,15 +10794,15 @@ namespace ts {
10794
10794
10795
10795
// In an assignment expression, the right operand is contextually typed by the type of the left operand.
10796
10796
if (node === binaryExpression.right) {
10797
- return checkExpression (binaryExpression.left);
10797
+ return getTypeOfExpression (binaryExpression.left);
10798
10798
}
10799
10799
}
10800
10800
else if (operator === SyntaxKind.BarBarToken) {
10801
10801
// When an || expression has a contextual type, the operands are contextually typed by that type. When an ||
10802
10802
// expression has no contextual type, the right operand is contextually typed by the type of the left operand.
10803
10803
let type = getContextualType(binaryExpression);
10804
10804
if (!type && node === binaryExpression.right) {
10805
- type = checkExpression (binaryExpression.left);
10805
+ type = getTypeOfExpression (binaryExpression.left);
10806
10806
}
10807
10807
return type;
10808
10808
}
@@ -12173,7 +12173,7 @@ namespace ts {
12173
12173
if (node.kind === SyntaxKind.ForInStatement &&
12174
12174
child === (<ForInStatement>node).statement &&
12175
12175
getForInVariableSymbol(<ForInStatement>node) === symbol &&
12176
- hasNumericPropertyNames(checkExpression ((<ForInStatement>node).expression))) {
12176
+ hasNumericPropertyNames(getTypeOfExpression ((<ForInStatement>node).expression))) {
12177
12177
return true;
12178
12178
}
12179
12179
child = node;
@@ -13809,7 +13809,7 @@ namespace ts {
13809
13809
if (!node.possiblyExhaustive) {
13810
13810
return false;
13811
13811
}
13812
- const type = checkExpression (node.expression);
13812
+ const type = getTypeOfExpression (node.expression);
13813
13813
if (!isLiteralType(type)) {
13814
13814
return false;
13815
13815
}
@@ -14901,6 +14901,24 @@ namespace ts {
14901
14901
return type;
14902
14902
}
14903
14903
14904
+ // Returns the type of an expression. Unlike checkExpression, this function is simply concerned
14905
+ // with computing the type and may not fully check all contained sub-expressions for errors.
14906
+ function getTypeOfExpression(node: Expression) {
14907
+ // Optimize for the common case of a call to a function with a single non-generic call
14908
+ // signature where we can just fetch the return type without checking the arguments.
14909
+ if (node.kind === SyntaxKind.CallExpression && (<CallExpression>node).expression.kind !== SyntaxKind.SuperKeyword) {
14910
+ const funcType = checkNonNullExpression((<CallExpression>node).expression);
14911
+ const signature = getSingleCallSignature(funcType);
14912
+ if (signature && !signature.typeParameters) {
14913
+ return getReturnTypeOfSignature(signature);
14914
+ }
14915
+ }
14916
+ // Otherwise simply call checkExpression. Ideally, the entire family of checkXXX functions
14917
+ // should have a parameter that indicates whether full error checking is required such that
14918
+ // we can perform the optimizations locally.
14919
+ return checkExpression(node);
14920
+ }
14921
+
14904
14922
// Checks an expression and returns its type. The contextualMapper parameter serves two purposes: When
14905
14923
// contextualMapper is not undefined and not equal to the identityMapper function object it indicates that the
14906
14924
// expression is being inferentially typed (section 4.15.2 in spec) and provides the type mapper to use in
@@ -18283,7 +18301,7 @@ namespace ts {
18283
18301
}
18284
18302
}
18285
18303
18286
- enumType = checkExpression (expression);
18304
+ enumType = getTypeOfExpression (expression);
18287
18305
// allow references to constant members of other enums
18288
18306
if (!(enumType.symbol && (enumType.symbol.flags & SymbolFlags.Enum))) {
18289
18307
return undefined;
@@ -19453,7 +19471,7 @@ namespace ts {
19453
19471
// fallthrough
19454
19472
19455
19473
case SyntaxKind.SuperKeyword:
19456
- const type = isPartOfExpression(node) ? checkExpression (<Expression>node) : getTypeFromTypeNode(<TypeNode>node);
19474
+ const type = isPartOfExpression(node) ? getTypeOfExpression (<Expression>node) : getTypeFromTypeNode(<TypeNode>node);
19457
19475
return type.symbol;
19458
19476
19459
19477
case SyntaxKind.ThisType:
@@ -19483,7 +19501,7 @@ namespace ts {
19483
19501
case SyntaxKind.NumericLiteral:
19484
19502
// index access
19485
19503
if (node.parent.kind === SyntaxKind.ElementAccessExpression && (<ElementAccessExpression>node.parent).argumentExpression === node) {
19486
- const objectType = checkExpression ((<ElementAccessExpression>node.parent).expression);
19504
+ const objectType = getTypeOfExpression ((<ElementAccessExpression>node.parent).expression);
19487
19505
if (objectType === unknownType) return undefined;
19488
19506
const apparentType = getApparentType(objectType);
19489
19507
if (apparentType === unknownType) return undefined;
@@ -19522,7 +19540,7 @@ namespace ts {
19522
19540
}
19523
19541
19524
19542
if (isPartOfExpression(node)) {
19525
- return getTypeOfExpression (<Expression>node);
19543
+ return getRegularTypeOfExpression (<Expression>node);
19526
19544
}
19527
19545
19528
19546
if (isExpressionWithTypeArgumentsInClassExtendsClause(node)) {
@@ -19584,7 +19602,7 @@ namespace ts {
19584
19602
// If this is from "for" initializer
19585
19603
// for ({a } = elems[0];.....) { }
19586
19604
if (expr.parent.kind === SyntaxKind.BinaryExpression) {
19587
- const iteratedType = checkExpression ((<BinaryExpression>expr.parent).right);
19605
+ const iteratedType = getTypeOfExpression ((<BinaryExpression>expr.parent).right);
19588
19606
return checkDestructuringAssignment(expr, iteratedType || unknownType);
19589
19607
}
19590
19608
// If this is from nested object binding pattern
@@ -19614,11 +19632,11 @@ namespace ts {
19614
19632
return typeOfObjectLiteral && getPropertyOfType(typeOfObjectLiteral, location.text);
19615
19633
}
19616
19634
19617
- function getTypeOfExpression (expr: Expression): Type {
19635
+ function getRegularTypeOfExpression (expr: Expression): Type {
19618
19636
if (isRightSideOfQualifiedNameOrPropertyAccess(expr)) {
19619
19637
expr = <Expression>expr.parent;
19620
19638
}
19621
- return getRegularTypeOfLiteralType(checkExpression (expr));
19639
+ return getRegularTypeOfLiteralType(getTypeOfExpression (expr));
19622
19640
}
19623
19641
19624
19642
/**
@@ -20045,7 +20063,7 @@ namespace ts {
20045
20063
}
20046
20064
20047
20065
function writeTypeOfExpression(expr: Expression, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter) {
20048
- const type = getWidenedType(getTypeOfExpression (expr));
20066
+ const type = getWidenedType(getRegularTypeOfExpression (expr));
20049
20067
getSymbolDisplayBuilder().buildTypeDisplay(type, writer, enclosingDeclaration, flags);
20050
20068
}
20051
20069
0 commit comments