Merge pull request #32904 from microsoft/getRidOfCrappyLiterals

Prefer reporting base primitives in various operations
This commit is contained in:
Daniel Rosenwasser
2019-08-14 17:47:18 -07:00
committed by GitHub
16 changed files with 201 additions and 180 deletions

View File

@@ -24086,7 +24086,7 @@ namespace ts {
}
if (node.operator === SyntaxKind.PlusToken) {
if (maybeTypeOfKind(operandType, TypeFlags.BigIntLike)) {
error(node.operand, Diagnostics.Operator_0_cannot_be_applied_to_type_1, tokenToString(node.operator), typeToString(operandType));
error(node.operand, Diagnostics.Operator_0_cannot_be_applied_to_type_1, tokenToString(node.operator), typeToString(getBaseTypeOfLiteralType(operandType)));
}
return numberType;
}
@@ -24521,7 +24521,7 @@ namespace ts {
resultType = numberType;
}
// At least one is assignable to bigint, so check that both are
else if (isTypeAssignableToKind(leftType, TypeFlags.BigIntLike) && isTypeAssignableToKind(rightType, TypeFlags.BigIntLike)) {
else if (bothAreBigIntLike(leftType, rightType)) {
switch (operator) {
case SyntaxKind.GreaterThanGreaterThanGreaterThanToken:
case SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken:
@@ -24531,7 +24531,7 @@ namespace ts {
}
// Exactly one of leftType/rightType is assignable to bigint
else {
reportOperatorError((awaitedLeft, awaitedRight) => isTypeAssignableToKind(awaitedLeft, TypeFlags.BigIntLike) && isTypeAssignableToKind(awaitedRight, TypeFlags.BigIntLike));
reportOperatorError(bothAreBigIntLike);
resultType = errorType;
}
if (leftOk && rightOk) {
@@ -24581,9 +24581,9 @@ namespace ts {
// might be missing an await without doing an exhaustive check that inserting
// await(s) will actually be a completely valid binary expression.
const closeEnoughKind = TypeFlags.NumberLike | TypeFlags.BigIntLike | TypeFlags.StringLike | TypeFlags.AnyOrUnknown;
reportOperatorError((awaitedLeft, awaitedRight) =>
isTypeAssignableToKind(awaitedLeft, closeEnoughKind) &&
isTypeAssignableToKind(awaitedRight, closeEnoughKind));
reportOperatorError((left, right) =>
isTypeAssignableToKind(left, closeEnoughKind) &&
isTypeAssignableToKind(right, closeEnoughKind));
return anyType;
}
@@ -24651,6 +24651,10 @@ namespace ts {
return Debug.fail();
}
function bothAreBigIntLike(left: Type, right: Type): boolean {
return isTypeAssignableToKind(left, TypeFlags.BigIntLike) && isTypeAssignableToKind(right, TypeFlags.BigIntLike);
}
function checkAssignmentDeclaration(kind: AssignmentDeclarationKind, rightType: Type) {
if (kind === AssignmentDeclarationKind.ModuleExports) {
for (const prop of getPropertiesOfObjectType(rightType)) {
@@ -24747,18 +24751,23 @@ namespace ts {
return false;
}
function reportOperatorError(awaitedTypesAreCompatible?: (left: Type, right: Type) => boolean) {
function reportOperatorError(isRelated?: (left: Type, right: Type) => boolean) {
let wouldWorkWithAwait = false;
const errNode = errorNode || operatorToken;
const [leftStr, rightStr] = getTypeNamesForErrorDisplay(leftType, rightType);
if (awaitedTypesAreCompatible) {
if (isRelated) {
const awaitedLeftType = getAwaitedType(leftType);
const awaitedRightType = getAwaitedType(rightType);
wouldWorkWithAwait = !(awaitedLeftType === leftType && awaitedRightType === rightType)
&& !!(awaitedLeftType && awaitedRightType)
&& awaitedTypesAreCompatible(awaitedLeftType, awaitedRightType);
&& isRelated(awaitedLeftType, awaitedRightType);
}
let effectiveLeft = leftType;
let effectiveRight = rightType;
if (!wouldWorkWithAwait && isRelated) {
[effectiveLeft, effectiveRight] = getBaseTypesIfUnrelated(leftType, rightType, isRelated);
}
const [leftStr, rightStr] = getTypeNamesForErrorDisplay(effectiveLeft, effectiveRight);
if (!tryGiveBetterPrimaryError(errNode, wouldWorkWithAwait, leftStr, rightStr)) {
errorAndMaybeSuggestAwait(
errNode,
@@ -24795,6 +24804,18 @@ namespace ts {
}
}
function getBaseTypesIfUnrelated(leftType: Type, rightType: Type, isRelated: (left: Type, right: Type) => boolean): [Type, Type] {
let effectiveLeft = leftType;
let effectiveRight = rightType;
const leftBase = getBaseTypeOfLiteralType(leftType);
const rightBase = getBaseTypeOfLiteralType(rightType);
if (!isRelated(leftBase, rightBase)) {
effectiveLeft = leftBase;
effectiveRight = rightBase;
}
return [ effectiveLeft, effectiveRight ];
}
function isYieldExpressionInClass(node: YieldExpression): boolean {
let current: Node = node;
let parent = node.parent;