mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-24 14:14:32 -06:00
Always keep literal types and widen when inferred as types for mutable locations
This commit is contained in:
parent
a8063dfb68
commit
adc015dc5e
@ -568,6 +568,9 @@ namespace ts {
|
||||
case SyntaxKind.PrefixUnaryExpression:
|
||||
bindPrefixUnaryExpressionFlow(<PrefixUnaryExpression>node);
|
||||
break;
|
||||
case SyntaxKind.PostfixUnaryExpression:
|
||||
bindPostfixUnaryExpressionFlow(<PostfixUnaryExpression>node);
|
||||
break;
|
||||
case SyntaxKind.BinaryExpression:
|
||||
bindBinaryExpressionFlow(<BinaryExpression>node);
|
||||
break;
|
||||
@ -1083,6 +1086,16 @@ namespace ts {
|
||||
}
|
||||
else {
|
||||
forEachChild(node, bind);
|
||||
if (node.operator === SyntaxKind.PlusEqualsToken || node.operator === SyntaxKind.MinusMinusToken) {
|
||||
bindAssignmentTargetFlow(node.operand);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function bindPostfixUnaryExpressionFlow(node: PostfixUnaryExpression) {
|
||||
forEachChild(node, bind);
|
||||
if (node.operator === SyntaxKind.PlusPlusToken || node.operator === SyntaxKind.MinusMinusToken) {
|
||||
bindAssignmentTargetFlow(node.operand);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -2914,7 +2914,7 @@ namespace ts {
|
||||
// undefined or any type of the parent.
|
||||
if (!parentType || isTypeAny(parentType)) {
|
||||
if (declaration.initializer) {
|
||||
return checkExpressionCached(declaration.initializer);
|
||||
return getBaseTypeOfLiteralType(checkExpressionCached(declaration.initializer));
|
||||
}
|
||||
return parentType;
|
||||
}
|
||||
@ -3109,7 +3109,7 @@ namespace ts {
|
||||
// pattern. Otherwise, it is the type any.
|
||||
function getTypeFromBindingElement(element: BindingElement, includePatternInType?: boolean, reportErrors?: boolean): Type {
|
||||
if (element.initializer) {
|
||||
return checkExpressionCached(element.initializer);
|
||||
return getBaseTypeOfLiteralType(checkExpressionCached(element.initializer));
|
||||
}
|
||||
if (isBindingPattern(element.name)) {
|
||||
return getTypeFromBindingPattern(<BindingPattern>element.name, includePatternInType, reportErrors);
|
||||
@ -7218,6 +7218,10 @@ namespace ts {
|
||||
type;
|
||||
}
|
||||
|
||||
function getBaseTypeIfUnitType(type: Type): Type {
|
||||
return isUnitType(type) ? getBaseTypeOfLiteralType(type) : type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a Type was written as a tuple type literal.
|
||||
* Prefer using isTupleLikeType() unless the use of `elementTypes` is required.
|
||||
@ -7504,6 +7508,11 @@ namespace ts {
|
||||
return type.couldContainTypeParameters;
|
||||
}
|
||||
|
||||
function hasPrimitiveConstraint(type: TypeParameter): boolean {
|
||||
const constraint = getConstraintOfTypeParameter(type);
|
||||
return constraint && (constraint.flags & (TypeFlags.String | TypeFlags.Number | TypeFlags.Boolean | TypeFlags.Enum)) !== 0;
|
||||
}
|
||||
|
||||
function inferTypes(context: InferenceContext, source: Type, target: Type) {
|
||||
let sourceStack: Type[];
|
||||
let targetStack: Type[];
|
||||
@ -7578,7 +7587,8 @@ namespace ts {
|
||||
const candidates = inferiority ?
|
||||
inferences.secondary || (inferences.secondary = []) :
|
||||
inferences.primary || (inferences.primary = []);
|
||||
const widened = isUnitType(source) ? getBaseTypeOfLiteralType(source): source;
|
||||
// Infer base primitive type for unit types.
|
||||
const widened = isUnitType(source) && !hasPrimitiveConstraint(<TypeParameter>target) ? getBaseTypeOfLiteralType(source) : source;
|
||||
if (!contains(candidates, widened)) {
|
||||
candidates.push(widened);
|
||||
}
|
||||
@ -8310,7 +8320,8 @@ namespace ts {
|
||||
// Assignments only narrow the computed type if the declared type is a union type. Thus, we
|
||||
// only need to evaluate the assigned type if the declared type is a union type.
|
||||
if (isMatchingReference(reference, node)) {
|
||||
return declaredType.flags & TypeFlags.Union ?
|
||||
const isIncrementOrDecrement = node.parent.kind === SyntaxKind.PrefixUnaryExpression || node.parent.kind === SyntaxKind.PostfixUnaryExpression;
|
||||
return declaredType.flags & TypeFlags.Union && !isIncrementOrDecrement ?
|
||||
getAssignmentReducedType(<UnionType>declaredType, getInitialOrAssignedType(node)) :
|
||||
declaredType;
|
||||
}
|
||||
@ -9402,14 +9413,14 @@ namespace ts {
|
||||
if (parameter.dotDotDotToken) {
|
||||
const restTypes: Type[] = [];
|
||||
for (let i = indexOfParameter; i < iife.arguments.length; i++) {
|
||||
restTypes.push(getTypeOfExpression(iife.arguments[i]));
|
||||
restTypes.push(getBaseTypeOfLiteralType(checkExpression(iife.arguments[i])));
|
||||
}
|
||||
return createArrayType(getUnionType(restTypes));
|
||||
}
|
||||
const links = getNodeLinks(iife);
|
||||
const cached = links.resolvedSignature;
|
||||
links.resolvedSignature = anySignature;
|
||||
const type = checkExpression(iife.arguments[indexOfParameter]);
|
||||
const type = getBaseTypeOfLiteralType(checkExpression(iife.arguments[indexOfParameter]));
|
||||
links.resolvedSignature = cached;
|
||||
return type;
|
||||
}
|
||||
@ -12263,7 +12274,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function checkAssertion(node: AssertionExpression) {
|
||||
const exprType = getRegularTypeOfObjectLiteral(checkExpression(node.expression));
|
||||
const exprType = getRegularTypeOfObjectLiteral(getBaseTypeOfLiteralType(checkExpression(node.expression)));
|
||||
|
||||
checkSourceElement(node.type);
|
||||
const targetType = getTypeFromTypeNode(node.type);
|
||||
@ -12455,9 +12466,6 @@ namespace ts {
|
||||
}
|
||||
// Return a union of the return expression types.
|
||||
type = getUnionType(types, /*subtypeReduction*/ true);
|
||||
if (isUnitType(type)) {
|
||||
type = getBaseTypeOfLiteralType(type);
|
||||
}
|
||||
|
||||
if (funcIsGenerator) {
|
||||
type = createIterableIteratorType(type);
|
||||
@ -12465,6 +12473,9 @@ namespace ts {
|
||||
}
|
||||
if (!contextualSignature) {
|
||||
reportErrorsFromWidening(func, type);
|
||||
if (isUnitType(type)) {
|
||||
type = getBaseTypeOfLiteralType(type);
|
||||
}
|
||||
}
|
||||
|
||||
const widenedType = getWidenedType(type);
|
||||
@ -13244,11 +13255,11 @@ namespace ts {
|
||||
case SyntaxKind.ExclamationEqualsToken:
|
||||
case SyntaxKind.EqualsEqualsEqualsToken:
|
||||
case SyntaxKind.ExclamationEqualsEqualsToken:
|
||||
const leftIsUnit = isLiteralType(leftType);
|
||||
const rightIsUnit = isLiteralType(rightType);
|
||||
if (!leftIsUnit || !rightIsUnit) {
|
||||
leftType = leftIsUnit ? getBaseTypeOfLiteralType(leftType) : leftType;
|
||||
rightType = rightIsUnit ? getBaseTypeOfLiteralType(rightType) : rightType;
|
||||
const leftIsLiteral = isLiteralType(leftType);
|
||||
const rightIsLiteral = isLiteralType(rightType);
|
||||
if (!leftIsLiteral || !rightIsLiteral) {
|
||||
leftType = leftIsLiteral ? getBaseTypeOfLiteralType(leftType) : leftType;
|
||||
rightType = rightIsLiteral ? getBaseTypeOfLiteralType(rightType) : rightType;
|
||||
}
|
||||
if (!isTypeEqualityComparableTo(leftType, rightType) && !isTypeEqualityComparableTo(rightType, leftType)) {
|
||||
reportOperatorError();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user