Skip to content

Prefer using enum literal's own base type rather than enum's base type in comparison #52703

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Feb 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22983,6 +22983,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
return getCachedType(key) ?? setCachedType(key, mapType(type, getBaseTypeOfLiteralType));
}

// This like getBaseTypeOfLiteralType, but instead treats enum literals as strings/numbers instead
// of returning their enum base type (which depends on the types of other literals in the enum).
function getBaseTypeOfLiteralTypeForComparison(type: Type): Type {
return type.flags & (TypeFlags.StringLiteral | TypeFlags.TemplateLiteral | TypeFlags.StringMapping) ? stringType :
type.flags & (TypeFlags.NumberLiteral | TypeFlags.Enum) ? numberType :
type.flags & TypeFlags.BigIntLiteral ? bigintType :
type.flags & TypeFlags.BooleanLiteral ? booleanType :
type.flags & TypeFlags.Union ? mapType(type, getBaseTypeOfLiteralTypeForComparison) :
type;
}

function getWidenedLiteralType(type: Type): Type {
return type.flags & TypeFlags.EnumLiteral && isFreshLiteralType(type) ? getBaseTypeOfEnumLiteralType(type as LiteralType) :
type.flags & TypeFlags.StringLiteral && isFreshLiteralType(type) ? stringType :
Expand Down Expand Up @@ -36423,8 +36434,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
case SyntaxKind.LessThanEqualsToken:
case SyntaxKind.GreaterThanEqualsToken:
if (checkForDisallowedESSymbolOperand(operator)) {
leftType = getBaseTypeOfLiteralType(checkNonNullType(leftType, left));
rightType = getBaseTypeOfLiteralType(checkNonNullType(rightType, right));
leftType = getBaseTypeOfLiteralTypeForComparison(checkNonNullType(leftType, left));
rightType = getBaseTypeOfLiteralTypeForComparison(checkNonNullType(rightType, right));
reportOperatorErrorUnless((left, right) => {
if (isTypeAny(left) || isTypeAny(right)) {
return true;
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -7,37 +7,37 @@ tests/cases/conformance/expressions/binaryOperators/comparisonOperator/compariso
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(18,14): error TS2367: This comparison appears to be unintentional because the types 'T' and 'U' have no overlap.
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(19,14): error TS2367: This comparison appears to be unintentional because the types 'T' and 'U' have no overlap.
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(23,16): error TS2365: Operator '<' cannot be applied to types 'T' and 'number'.
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(26,16): error TS2365: Operator '<' cannot be applied to types 'T' and 'E'.
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(26,16): error TS2365: Operator '<' cannot be applied to types 'T' and 'number'.
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(31,16): error TS2365: Operator '<' cannot be applied to types 'number' and 'T'.
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(34,16): error TS2365: Operator '<' cannot be applied to types 'E' and 'T'.
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(34,16): error TS2365: Operator '<' cannot be applied to types 'number' and 'T'.
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(40,16): error TS2365: Operator '<' cannot be applied to types 'T' and 'number'.
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(43,16): error TS2365: Operator '<' cannot be applied to types 'T' and 'E'.
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(43,16): error TS2365: Operator '<' cannot be applied to types 'T' and 'number'.
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(48,16): error TS2365: Operator '<' cannot be applied to types 'number' and 'T'.
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(51,16): error TS2365: Operator '<' cannot be applied to types 'E' and 'T'.
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(51,16): error TS2365: Operator '<' cannot be applied to types 'number' and 'T'.
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(57,16): error TS2365: Operator '<' cannot be applied to types 'T' and 'number'.
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(60,16): error TS2365: Operator '<' cannot be applied to types 'T' and 'E'.
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(60,16): error TS2365: Operator '<' cannot be applied to types 'T' and 'number'.
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(65,16): error TS2365: Operator '<' cannot be applied to types 'number' and 'T'.
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(68,16): error TS2365: Operator '<' cannot be applied to types 'E' and 'T'.
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(68,16): error TS2365: Operator '<' cannot be applied to types 'number' and 'T'.
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(74,16): error TS2365: Operator '<' cannot be applied to types 'T' and 'number'.
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(77,16): error TS2365: Operator '<' cannot be applied to types 'T' and 'E'.
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(77,16): error TS2365: Operator '<' cannot be applied to types 'T' and 'number'.
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(82,16): error TS2365: Operator '<' cannot be applied to types 'number' and 'T'.
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(85,16): error TS2365: Operator '<' cannot be applied to types 'E' and 'T'.
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(85,16): error TS2365: Operator '<' cannot be applied to types 'number' and 'T'.
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(91,16): error TS2365: Operator '<' cannot be applied to types 'T' and 'number'.
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(94,16): error TS2365: Operator '<' cannot be applied to types 'T' and 'E'.
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(94,16): error TS2365: Operator '<' cannot be applied to types 'T' and 'number'.
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(99,16): error TS2365: Operator '<' cannot be applied to types 'number' and 'T'.
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(102,16): error TS2365: Operator '<' cannot be applied to types 'E' and 'T'.
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(102,16): error TS2365: Operator '<' cannot be applied to types 'number' and 'T'.
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(108,16): error TS2365: Operator '<' cannot be applied to types 'T' and 'number'.
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(111,16): error TS2365: Operator '<' cannot be applied to types 'T' and 'E'.
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(111,16): error TS2365: Operator '<' cannot be applied to types 'T' and 'number'.
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(116,16): error TS2365: Operator '<' cannot be applied to types 'number' and 'T'.
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(119,16): error TS2365: Operator '<' cannot be applied to types 'E' and 'T'.
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(119,16): error TS2365: Operator '<' cannot be applied to types 'number' and 'T'.
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(125,16): error TS2365: Operator '<' cannot be applied to types 'T' and 'number'.
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(128,16): error TS2365: Operator '<' cannot be applied to types 'T' and 'E'.
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(128,16): error TS2365: Operator '<' cannot be applied to types 'T' and 'number'.
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(133,16): error TS2365: Operator '<' cannot be applied to types 'number' and 'T'.
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(136,16): error TS2365: Operator '<' cannot be applied to types 'E' and 'T'.
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(136,16): error TS2365: Operator '<' cannot be applied to types 'number' and 'T'.
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(142,16): error TS2365: Operator '<' cannot be applied to types 'T' and 'number'.
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(145,16): error TS2365: Operator '<' cannot be applied to types 'T' and 'E'.
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(145,16): error TS2365: Operator '<' cannot be applied to types 'T' and 'number'.
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(150,16): error TS2365: Operator '<' cannot be applied to types 'number' and 'T'.
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(153,16): error TS2365: Operator '<' cannot be applied to types 'E' and 'T'.
tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts(153,16): error TS2365: Operator '<' cannot be applied to types 'number' and 'T'.


==== tests/cases/conformance/expressions/binaryOperators/comparisonOperator/comparisonOperatorWithNoRelationshipTypeParameter.ts (40 errors) ====
Expand Down Expand Up @@ -86,7 +86,7 @@ tests/cases/conformance/expressions/binaryOperators/comparisonOperator/compariso
var r1a4 = t < d;
var r1a5 = t < e;
~~~~~
!!! error TS2365: Operator '<' cannot be applied to types 'T' and 'E'.
!!! error TS2365: Operator '<' cannot be applied to types 'T' and 'number'.
var r1a6 = t < f;
var r1a7 = t < g;

Expand All @@ -98,7 +98,7 @@ tests/cases/conformance/expressions/binaryOperators/comparisonOperator/compariso
var r1b4 = d < t;
var r1b5 = e < t;
~~~~~
!!! error TS2365: Operator '<' cannot be applied to types 'E' and 'T'.
!!! error TS2365: Operator '<' cannot be applied to types 'number' and 'T'.
var r1b6 = f < t;
var r1b7 = g < t;

Expand All @@ -111,7 +111,7 @@ tests/cases/conformance/expressions/binaryOperators/comparisonOperator/compariso
var r2a4 = t < d;
var r2a5 = t < e;
~~~~~
!!! error TS2365: Operator '<' cannot be applied to types 'T' and 'E'.
!!! error TS2365: Operator '<' cannot be applied to types 'T' and 'number'.
var r2a6 = t < f;
var r2a7 = t < g;

Expand All @@ -123,7 +123,7 @@ tests/cases/conformance/expressions/binaryOperators/comparisonOperator/compariso
var r2b4 = d < t;
var r2b5 = e < t;
~~~~~
!!! error TS2365: Operator '<' cannot be applied to types 'E' and 'T'.
!!! error TS2365: Operator '<' cannot be applied to types 'number' and 'T'.
var r2b6 = f < t;
var r2b7 = g < t;

Expand All @@ -136,7 +136,7 @@ tests/cases/conformance/expressions/binaryOperators/comparisonOperator/compariso
var r3a4 = t < d;
var r3a5 = t < e;
~~~~~
!!! error TS2365: Operator '<' cannot be applied to types 'T' and 'E'.
!!! error TS2365: Operator '<' cannot be applied to types 'T' and 'number'.
var r3a6 = t < f;
var r3a7 = t < g;

Expand All @@ -148,7 +148,7 @@ tests/cases/conformance/expressions/binaryOperators/comparisonOperator/compariso
var r3b4 = d < t;
var r3b5 = e < t;
~~~~~
!!! error TS2365: Operator '<' cannot be applied to types 'E' and 'T'.
!!! error TS2365: Operator '<' cannot be applied to types 'number' and 'T'.
var r3b6 = f < t;
var r3b7 = g < t;

Expand All @@ -161,7 +161,7 @@ tests/cases/conformance/expressions/binaryOperators/comparisonOperator/compariso
var r4a4 = t < d;
var r4a5 = t < e;
~~~~~
!!! error TS2365: Operator '<' cannot be applied to types 'T' and 'E'.
!!! error TS2365: Operator '<' cannot be applied to types 'T' and 'number'.
var r4a6 = t < f;
var r4a7 = t < g;

Expand All @@ -173,7 +173,7 @@ tests/cases/conformance/expressions/binaryOperators/comparisonOperator/compariso
var r4b4 = d < t;
var r4b5 = e < t;
~~~~~
!!! error TS2365: Operator '<' cannot be applied to types 'E' and 'T'.
!!! error TS2365: Operator '<' cannot be applied to types 'number' and 'T'.
var r4b6 = f < t;
var r4b7 = g < t;

Expand All @@ -186,7 +186,7 @@ tests/cases/conformance/expressions/binaryOperators/comparisonOperator/compariso
var r5a4 = t < d;
var r5a5 = t < e;
~~~~~
!!! error TS2365: Operator '<' cannot be applied to types 'T' and 'E'.
!!! error TS2365: Operator '<' cannot be applied to types 'T' and 'number'.
var r5a6 = t < f;
var r5a7 = t < g;

Expand All @@ -198,7 +198,7 @@ tests/cases/conformance/expressions/binaryOperators/comparisonOperator/compariso
var r5b4 = d < t;
var r5b5 = e < t;
~~~~~
!!! error TS2365: Operator '<' cannot be applied to types 'E' and 'T'.
!!! error TS2365: Operator '<' cannot be applied to types 'number' and 'T'.
var r5b6 = f < t;
var r5b7 = g < t;

Expand All @@ -211,7 +211,7 @@ tests/cases/conformance/expressions/binaryOperators/comparisonOperator/compariso
var r6a4 = t < d;
var r6a5 = t < e;
~~~~~
!!! error TS2365: Operator '<' cannot be applied to types 'T' and 'E'.
!!! error TS2365: Operator '<' cannot be applied to types 'T' and 'number'.
var r6a6 = t < f;
var r6a7 = t < g;

Expand All @@ -223,7 +223,7 @@ tests/cases/conformance/expressions/binaryOperators/comparisonOperator/compariso
var r6b4 = d < t;
var r6b5 = e < t;
~~~~~
!!! error TS2365: Operator '<' cannot be applied to types 'E' and 'T'.
!!! error TS2365: Operator '<' cannot be applied to types 'number' and 'T'.
var r6b6 = f < t;
var r6b7 = g < t;

Expand All @@ -236,7 +236,7 @@ tests/cases/conformance/expressions/binaryOperators/comparisonOperator/compariso
var r7a4 = t < d;
var r7a5 = t < e;
~~~~~
!!! error TS2365: Operator '<' cannot be applied to types 'T' and 'E'.
!!! error TS2365: Operator '<' cannot be applied to types 'T' and 'number'.
var r7a6 = t < f;
var r7a7 = t < g;

Expand All @@ -248,7 +248,7 @@ tests/cases/conformance/expressions/binaryOperators/comparisonOperator/compariso
var r7b4 = d < t;
var r7b5 = e < t;
~~~~~
!!! error TS2365: Operator '<' cannot be applied to types 'E' and 'T'.
!!! error TS2365: Operator '<' cannot be applied to types 'number' and 'T'.
var r7b6 = f < t;
var r7b7 = g < t;

Expand All @@ -261,7 +261,7 @@ tests/cases/conformance/expressions/binaryOperators/comparisonOperator/compariso
var r8a4 = t < d;
var r8a5 = t < e;
~~~~~
!!! error TS2365: Operator '<' cannot be applied to types 'T' and 'E'.
!!! error TS2365: Operator '<' cannot be applied to types 'T' and 'number'.
var r8a6 = t < f;
var r8a7 = t < g;

Expand All @@ -273,7 +273,7 @@ tests/cases/conformance/expressions/binaryOperators/comparisonOperator/compariso
var r8b4 = d < t;
var r8b5 = e < t;
~~~~~
!!! error TS2365: Operator '<' cannot be applied to types 'E' and 'T'.
!!! error TS2365: Operator '<' cannot be applied to types 'number' and 'T'.
var r8b6 = f < t;
var r8b7 = g < t;
}
61 changes: 61 additions & 0 deletions tests/baselines/reference/mixedTypeEnumComparison.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
//// [mixedTypeEnumComparison.ts]
const enum E {
S1 = "foo",
S2 = "bar",

N1 = 1000,
N2 = 25,
}

declare var someNumber: number

if (someNumber > E.N2) {
someNumber = E.N2;
}

declare const unionOfEnum: E.N1 | E.N2;

if (someNumber > unionOfEnum) {
someNumber = E.N2;
}

declare var someString: string

if (someString > E.S1) {
someString = E.S2;
}


declare function someValue(): number;

enum E2 {
S1 = "foo",
N1 = 1000,
C1 = someValue(),
}

someString > E2.S1;
someNumber > E2.N1;
someNumber > E2.C1;


//// [mixedTypeEnumComparison.js]
"use strict";
if (someNumber > 25 /* E.N2 */) {
someNumber = 25 /* E.N2 */;
}
if (someNumber > unionOfEnum) {
someNumber = 25 /* E.N2 */;
}
if (someString > "foo" /* E.S1 */) {
someString = "bar" /* E.S2 */;
}
var E2;
(function (E2) {
E2["S1"] = "foo";
E2[E2["N1"] = 1000] = "N1";
E2[E2["C1"] = someValue()] = "C1";
})(E2 || (E2 = {}));
someString > E2.S1;
someNumber > E2.N1;
someNumber > E2.C1;
Loading