diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index d7acedd663d..aefdeea9ffe 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -10893,7 +10893,7 @@ namespace ts { // we defer subtype reduction until the evolving array type is finalized into a manifest // array type. function addEvolvingArrayElementType(evolvingArrayType: EvolvingArrayType, node: Expression): EvolvingArrayType { - const elementType = getBaseTypeOfLiteralType(getTypeOfExpression(node)); + const elementType = getBaseTypeOfLiteralType(getContextFreeTypeOfExpression(node)); return isTypeSubsetOf(elementType, evolvingArrayType.elementType) ? evolvingArrayType : getEvolvingArrayType(getUnionType([evolvingArrayType.elementType, elementType])); } @@ -17064,10 +17064,12 @@ namespace ts { return type; } - // Returns the type of an expression. Unlike checkExpression, this function is simply concerned - // with computing the type and may not fully check all contained sub-expressions for errors. - // A cache argument of true indicates that if the function performs a full type check, it is ok - // to cache the result. + /** + * Returns the type of an expression. Unlike checkExpression, this function is simply concerned + * with computing the type and may not fully check all contained sub-expressions for errors. + * A cache argument of true indicates that if the function performs a full type check, it is ok + * to cache the result. + */ function getTypeOfExpression(node: Expression, cache?: boolean) { // Optimize for the common case of a call to a function with a single non-generic call // signature where we can just fetch the return type without checking the arguments. @@ -17084,6 +17086,21 @@ namespace ts { return cache ? checkExpressionCached(node) : checkExpression(node); } + /** + * Returns the type of an expression. Unlike checkExpression, this function is simply concerned + * with computing the type and may not fully check all contained sub-expressions for errors. + * It is intended for uses where you know there is no contextual type, + * and requesting the contextual type might cause a circularity or other bad behaviour. + * It sets the contextual type of the node to any before calling getTypeOfExpression. + */ + function getContextFreeTypeOfExpression(node: Expression) { + const saveContextualType = node.contextualType; + node.contextualType = anyType; + const type = getTypeOfExpression(node); + node.contextualType = saveContextualType; + return type; + } + // Checks an expression and returns its type. The contextualMapper parameter serves two purposes: When // contextualMapper is not undefined and not equal to the identityMapper function object it indicates that the // expression is being inferentially typed (section 4.15.2 in spec) and provides the type mapper to use in