No widening of inferred type when initializer has a type assertion

This commit is contained in:
Anders Hejlsberg 2016-09-12 15:55:52 -07:00
parent b526aa3329
commit 816808c098

View file

@ -2919,7 +2919,7 @@ namespace ts {
// undefined or any type of the parent.
if (!parentType || isTypeAny(parentType)) {
if (declaration.initializer) {
return getBaseTypeOfLiteralType(checkExpressionCached(declaration.initializer));
return checkDeclarationInitializer(declaration);
}
return parentType;
}
@ -3090,8 +3090,7 @@ namespace ts {
// Use the type of the initializer expression if one is present
if (declaration.initializer) {
const exprType = checkExpressionCached(declaration.initializer);
const type = getCombinedNodeFlags(declaration) & NodeFlags.Const || getCombinedModifierFlags(declaration) & ModifierFlags.Readonly ? exprType : getBaseTypeOfLiteralType(exprType);
const type = checkDeclarationInitializer(declaration);
return addOptionality(type, /*optional*/ declaration.questionToken && includeOptionality);
}
@ -3114,8 +3113,7 @@ namespace ts {
// pattern. Otherwise, it is the type any.
function getTypeFromBindingElement(element: BindingElement, includePatternInType?: boolean, reportErrors?: boolean): Type {
if (element.initializer) {
const exprType = checkExpressionCached(element.initializer);
return getCombinedNodeFlags(element) & NodeFlags.Const ? exprType : getBaseTypeOfLiteralType(exprType);
return checkDeclarationInitializer(element);
}
if (isBindingPattern(element.name)) {
return getTypeFromBindingPattern(<BindingPattern>element.name, includePatternInType, reportErrors);
@ -13558,6 +13556,18 @@ namespace ts {
return links.resolvedType;
}
function isTypeAssertion(node: Expression) {
node = skipParenthesizedNodes(node);
return node.kind === SyntaxKind.TypeAssertionExpression || node.kind === SyntaxKind.AsExpression;
}
function checkDeclarationInitializer(declaration: VariableLikeDeclaration) {
const type = checkExpressionCached(declaration.initializer);
return getCombinedNodeFlags(declaration) & NodeFlags.Const ||
getCombinedModifierFlags(declaration) & ModifierFlags.Readonly ||
isTypeAssertion(declaration.initializer) ? type : getBaseTypeOfLiteralType(type);
}
function isLiteralContextualType(contextualType: Type) {
if (contextualType) {
if (contextualType.flags & TypeFlags.TypeParameter) {
@ -13577,7 +13587,7 @@ namespace ts {
function checkExpressionForMutableLocation(node: Expression, contextualMapper?: TypeMapper): Type {
const type = checkExpression(node, contextualMapper);
return isLiteralContextualType(getContextualType(node)) ? type : getBaseTypeOfLiteralType(type);
return isTypeAssertion(node) || isLiteralContextualType(getContextualType(node)) ? type : getBaseTypeOfLiteralType(type);
}
function checkPropertyAssignment(node: PropertyAssignment, contextualMapper?: TypeMapper): Type {