From 60ff10441bcfcfe11bed7a705d87438c14394666 Mon Sep 17 00:00:00 2001 From: Philippe Martin Date: Tue, 16 Oct 2018 18:31:10 +0200 Subject: [PATCH] Flag non-any/number/string operands on either side of comparison as errors Fixes #15506 --- src/compiler/checker.ts | 19 ++++++++++++-- ...ratorWithIdenticalPrimitiveType.errors.txt | 26 ++++++++++++++++++- 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ed65908d9267c..621edbf8f8b84 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -22698,8 +22698,10 @@ namespace ts { if (checkForDisallowedESSymbolOperand(operator)) { leftType = getBaseTypeOfLiteralType(checkNonNullType(leftType, left)); rightType = getBaseTypeOfLiteralType(checkNonNullType(rightType, right)); - if (!(isTypeComparableTo(leftType, rightType) || isTypeComparableTo(rightType, leftType) || - (isTypeAssignableTo(leftType, numberOrBigIntType) && isTypeAssignableTo(rightType, numberOrBigIntType)) + if (!checkTypeComparableWithLessOrGreaterThanOperator(leftType) && + !checkTypeComparableWithLessOrGreaterThanOperator(rightType) || + !(isTypeComparableTo(leftType, rightType) || isTypeComparableTo(rightType, leftType) || + (isTypeAssignableTo(leftType, numberOrBigIntType) && isTypeAssignableTo(rightType, numberOrBigIntType)) )) { reportOperatorError(); } @@ -22760,6 +22762,19 @@ namespace ts { return Debug.fail(); } + function checkTypeComparableWithLessOrGreaterThanOperator(valueType: Type): boolean { + const t = valueType.flags; + return (t === TypeFlags.String) || + (t === TypeFlags.Number) || + (t === TypeFlags.Any) || + (t === TypeFlags.TypeParameter) || + (t === TypeFlags.Enum) || + (t === TypeFlags.Object) || + (t === TypeFlags.Intersection) || + (t === (TypeFlags.EnumLiteral | TypeFlags.Union)) || + (t === (TypeFlags.Union)); + } + function checkAssignmentDeclaration(kind: AssignmentDeclarationKind, rightType: Type) { if (kind === AssignmentDeclarationKind.ModuleExports) { for (const prop of getPropertiesOfObjectType(rightType)) { diff --git a/tests/baselines/reference/comparisonOperatorWithIdenticalPrimitiveType.errors.txt b/tests/baselines/reference/comparisonOperatorWithIdenticalPrimitiveType.errors.txt index ad41a280aad3c..120e0a1f164e3 100644 --- a/tests/baselines/reference/comparisonOperatorWithIdenticalPrimitiveType.errors.txt +++ b/tests/baselines/reference/comparisonOperatorWithIdenticalPrimitiveType.errors.txt @@ -1,22 +1,30 @@ +tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithIdenticalPrimitiveType.ts(11,11): error TS2365: Operator '<' cannot be applied to types 'boolean' and 'boolean'. +tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithIdenticalPrimitiveType.ts(13,11): error TS2365: Operator '<' cannot be applied to types 'void' and 'void'. tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithIdenticalPrimitiveType.ts(15,11): error TS2531: Object is possibly 'null'. tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithIdenticalPrimitiveType.ts(15,18): error TS2531: Object is possibly 'null'. tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithIdenticalPrimitiveType.ts(16,11): error TS2532: Object is possibly 'undefined'. tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithIdenticalPrimitiveType.ts(16,23): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithIdenticalPrimitiveType.ts(20,11): error TS2365: Operator '>' cannot be applied to types 'boolean' and 'boolean'. +tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithIdenticalPrimitiveType.ts(22,11): error TS2365: Operator '>' cannot be applied to types 'void' and 'void'. tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithIdenticalPrimitiveType.ts(24,11): error TS2531: Object is possibly 'null'. tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithIdenticalPrimitiveType.ts(24,18): error TS2531: Object is possibly 'null'. tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithIdenticalPrimitiveType.ts(25,11): error TS2532: Object is possibly 'undefined'. tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithIdenticalPrimitiveType.ts(25,23): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithIdenticalPrimitiveType.ts(29,11): error TS2365: Operator '<=' cannot be applied to types 'boolean' and 'boolean'. +tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithIdenticalPrimitiveType.ts(31,11): error TS2365: Operator '<=' cannot be applied to types 'void' and 'void'. tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithIdenticalPrimitiveType.ts(33,11): error TS2531: Object is possibly 'null'. tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithIdenticalPrimitiveType.ts(33,19): error TS2531: Object is possibly 'null'. tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithIdenticalPrimitiveType.ts(34,11): error TS2532: Object is possibly 'undefined'. tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithIdenticalPrimitiveType.ts(34,24): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithIdenticalPrimitiveType.ts(38,11): error TS2365: Operator '>=' cannot be applied to types 'boolean' and 'boolean'. +tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithIdenticalPrimitiveType.ts(40,11): error TS2365: Operator '>=' cannot be applied to types 'void' and 'void'. tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithIdenticalPrimitiveType.ts(42,11): error TS2531: Object is possibly 'null'. tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithIdenticalPrimitiveType.ts(42,19): error TS2531: Object is possibly 'null'. tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithIdenticalPrimitiveType.ts(43,11): error TS2532: Object is possibly 'undefined'. tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithIdenticalPrimitiveType.ts(43,24): error TS2532: Object is possibly 'undefined'. -==== tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithIdenticalPrimitiveType.ts (16 errors) ==== +==== tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithIdenticalPrimitiveType.ts (24 errors) ==== enum E { a, b, c } var a: number; @@ -28,8 +36,12 @@ tests/cases/conformance/expressions/binaryOperators/comparisonOperator/compariso // operator < var ra1 = a < a; var ra2 = b < b; + ~~~~~ +!!! error TS2365: Operator '<' cannot be applied to types 'boolean' and 'boolean'. var ra3 = c < c; var ra4 = d < d; + ~~~~~ +!!! error TS2365: Operator '<' cannot be applied to types 'void' and 'void'. var ra5 = e < e; var ra6 = null < null; ~~~~ @@ -45,8 +57,12 @@ tests/cases/conformance/expressions/binaryOperators/comparisonOperator/compariso // operator > var rb1 = a > a; var rb2 = b > b; + ~~~~~ +!!! error TS2365: Operator '>' cannot be applied to types 'boolean' and 'boolean'. var rb3 = c > c; var rb4 = d > d; + ~~~~~ +!!! error TS2365: Operator '>' cannot be applied to types 'void' and 'void'. var rb5 = e > e; var rb6 = null > null; ~~~~ @@ -62,8 +78,12 @@ tests/cases/conformance/expressions/binaryOperators/comparisonOperator/compariso // operator <= var rc1 = a <= a; var rc2 = b <= b; + ~~~~~~ +!!! error TS2365: Operator '<=' cannot be applied to types 'boolean' and 'boolean'. var rc3 = c <= c; var rc4 = d <= d; + ~~~~~~ +!!! error TS2365: Operator '<=' cannot be applied to types 'void' and 'void'. var rc5 = e <= e; var rc6 = null <= null; ~~~~ @@ -79,8 +99,12 @@ tests/cases/conformance/expressions/binaryOperators/comparisonOperator/compariso // operator >= var rd1 = a >= a; var rd2 = b >= b; + ~~~~~~ +!!! error TS2365: Operator '>=' cannot be applied to types 'boolean' and 'boolean'. var rd3 = c >= c; var rd4 = d >= d; + ~~~~~~ +!!! error TS2365: Operator '>=' cannot be applied to types 'void' and 'void'. var rd5 = e >= e; var rd6 = null >= null; ~~~~