Skip to content

Commit

Permalink
allow literan enum const assertions (#30700)
Browse files Browse the repository at this point in the history
* allow literan enum const assertions

* update desc
  • Loading branch information
Kingwl authored and RyanCavanaugh committed Apr 25, 2019
1 parent b010010 commit bc46c77
Show file tree
Hide file tree
Showing 8 changed files with 520 additions and 8 deletions.
9 changes: 8 additions & 1 deletion src/compiler/checker.ts
Expand Up @@ -21973,6 +21973,13 @@ namespace ts {
const arg = (<PrefixUnaryExpression>node).operand;
return op === SyntaxKind.MinusToken && (arg.kind === SyntaxKind.NumericLiteral || arg.kind === SyntaxKind.BigIntLiteral) ||
op === SyntaxKind.PlusToken && arg.kind === SyntaxKind.NumericLiteral;
case SyntaxKind.PropertyAccessExpression:
case SyntaxKind.ElementAccessExpression:
const expr = (<PropertyAccessExpression | ElementAccessExpression>node).expression;
if (isIdentifier(expr)) {
const symbol = getSymbolAtLocation(expr);
return !!(symbol && (symbol.flags & SymbolFlags.Enum) && getEnumKind(symbol) === EnumKind.Literal);
}
}
return false;
}
Expand All @@ -21981,7 +21988,7 @@ namespace ts {
let exprType = checkExpression(expression, checkMode);
if (isConstTypeReference(type)) {
if (!isValidConstAssertionArgument(expression)) {
error(expression, Diagnostics.A_const_assertion_can_only_be_applied_to_a_string_number_boolean_array_or_object_literal);
error(expression, Diagnostics.A_const_assertions_can_only_be_applied_to_references_to_enum_members_or_string_number_boolean_array_or_object_literals);
}
return getRegularTypeOfLiteralType(exprType);
}
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/diagnosticMessages.json
Expand Up @@ -1031,7 +1031,7 @@
"category": "Error",
"code": 1354
},
"A 'const' assertion can only be applied to a string, number, boolean, array, or object literal.": {
"A 'const' assertions can only be applied to references to enum members, or string, number, boolean, array, or object literals.": {
"category": "Error",
"code": 1355
},
Expand Down
12 changes: 6 additions & 6 deletions tests/baselines/reference/constAssertions.errors.txt
@@ -1,7 +1,7 @@
tests/cases/conformance/expressions/typeAssertions/constAssertions.ts(44,32): error TS2540: Cannot assign to 'x' because it is a read-only property.
tests/cases/conformance/expressions/typeAssertions/constAssertions.ts(61,10): error TS1355: A 'const' assertion can only be applied to a string, number, boolean, array, or object literal.
tests/cases/conformance/expressions/typeAssertions/constAssertions.ts(62,10): error TS1355: A 'const' assertion can only be applied to a string, number, boolean, array, or object literal.
tests/cases/conformance/expressions/typeAssertions/constAssertions.ts(63,10): error TS1355: A 'const' assertion can only be applied to a string, number, boolean, array, or object literal.
tests/cases/conformance/expressions/typeAssertions/constAssertions.ts(61,10): error TS1355: A 'const' assertions can only be applied to references to enum members, or string, number, boolean, array, or object literals.
tests/cases/conformance/expressions/typeAssertions/constAssertions.ts(62,10): error TS1355: A 'const' assertions can only be applied to references to enum members, or string, number, boolean, array, or object literals.
tests/cases/conformance/expressions/typeAssertions/constAssertions.ts(63,10): error TS1355: A 'const' assertions can only be applied to references to enum members, or string, number, boolean, array, or object literals.


==== tests/cases/conformance/expressions/typeAssertions/constAssertions.ts (4 errors) ====
Expand Down Expand Up @@ -69,11 +69,11 @@ tests/cases/conformance/expressions/typeAssertions/constAssertions.ts(63,10): er

let e1 = v1 as const; // Error
~~
!!! error TS1355: A 'const' assertion can only be applied to a string, number, boolean, array, or object literal.
!!! error TS1355: A 'const' assertions can only be applied to references to enum members, or string, number, boolean, array, or object literals.
let e2 = (true ? 1 : 0) as const; // Error
~~~~~~~~~~~~~~
!!! error TS1355: A 'const' assertion can only be applied to a string, number, boolean, array, or object literal.
!!! error TS1355: A 'const' assertions can only be applied to references to enum members, or string, number, boolean, array, or object literals.
let e3 = id(1) as const; // Error
~~~~~
!!! error TS1355: A 'const' assertion can only be applied to a string, number, boolean, array, or object literal.
!!! error TS1355: A 'const' assertions can only be applied to references to enum members, or string, number, boolean, array, or object literals.

59 changes: 59 additions & 0 deletions tests/baselines/reference/constantEnumAssert.errors.txt
@@ -0,0 +1,59 @@
tests/cases/compiler/constantEnumAssert.ts(45,20): error TS1355: A 'const' assertions can only be applied to references to enum members, or string, number, boolean, array, or object literals.
tests/cases/compiler/constantEnumAssert.ts(49,20): error TS1355: A 'const' assertions can only be applied to references to enum members, or string, number, boolean, array, or object literals.


==== tests/cases/compiler/constantEnumAssert.ts (2 errors) ====
enum E1 {
a,
b
}

enum E2 {
a = 'a',
b = 'b'
}

enum E3 {
a = 1,
b = a << 1,
c = a << 2,
}

const enum E4 {
a,
b
}

const E5 = {
a: 'a',
b: 'b'
}

const foo1 = { a: E1.a }

const foo2 = { a: E2.a }

const foo3 = { a: E1.a } as const

const foo4 = { a: E2.a } as const

const foo5 = { a: E3.a } as const

const foo6 = { a: E4.a } as const

const foo7 = { a: E5.a } as const

const foo8 = { a: E1.a as const }

const foo9 = { a: E2.a as const }

const foo10 = { a: E3.a as const }
~~~~
!!! error TS1355: A 'const' assertions can only be applied to references to enum members, or string, number, boolean, array, or object literals.

const foo11 = { a: E4.a as const }

const foo12 = { a: E5.a as const }
~~~~
!!! error TS1355: A 'const' assertions can only be applied to references to enum members, or string, number, boolean, array, or object literals.

85 changes: 85 additions & 0 deletions tests/baselines/reference/constantEnumAssert.js
@@ -0,0 +1,85 @@
//// [constantEnumAssert.ts]
enum E1 {
a,
b
}

enum E2 {
a = 'a',
b = 'b'
}

enum E3 {
a = 1,
b = a << 1,
c = a << 2,
}

const enum E4 {
a,
b
}

const E5 = {
a: 'a',
b: 'b'
}

const foo1 = { a: E1.a }

const foo2 = { a: E2.a }

const foo3 = { a: E1.a } as const

const foo4 = { a: E2.a } as const

const foo5 = { a: E3.a } as const

const foo6 = { a: E4.a } as const

const foo7 = { a: E5.a } as const

const foo8 = { a: E1.a as const }

const foo9 = { a: E2.a as const }

const foo10 = { a: E3.a as const }

const foo11 = { a: E4.a as const }

const foo12 = { a: E5.a as const }


//// [constantEnumAssert.js]
var E1;
(function (E1) {
E1[E1["a"] = 0] = "a";
E1[E1["b"] = 1] = "b";
})(E1 || (E1 = {}));
var E2;
(function (E2) {
E2["a"] = "a";
E2["b"] = "b";
})(E2 || (E2 = {}));
var E3;
(function (E3) {
E3[E3["a"] = 1] = "a";
E3[E3["b"] = 2] = "b";
E3[E3["c"] = 4] = "c";
})(E3 || (E3 = {}));
var E5 = {
a: 'a',
b: 'b'
};
var foo1 = { a: E1.a };
var foo2 = { a: E2.a };
var foo3 = { a: E1.a };
var foo4 = { a: E2.a };
var foo5 = { a: E3.a };
var foo6 = { a: 0 /* a */ };
var foo7 = { a: E5.a };
var foo8 = { a: E1.a };
var foo9 = { a: E2.a };
var foo10 = { a: E3.a };
var foo11 = { a: 0 /* a */ };
var foo12 = { a: E5.a };
140 changes: 140 additions & 0 deletions tests/baselines/reference/constantEnumAssert.symbols
@@ -0,0 +1,140 @@
=== tests/cases/compiler/constantEnumAssert.ts ===
enum E1 {
>E1 : Symbol(E1, Decl(constantEnumAssert.ts, 0, 0))

a,
>a : Symbol(E1.a, Decl(constantEnumAssert.ts, 0, 9))

b
>b : Symbol(E1.b, Decl(constantEnumAssert.ts, 1, 6))
}

enum E2 {
>E2 : Symbol(E2, Decl(constantEnumAssert.ts, 3, 1))

a = 'a',
>a : Symbol(E2.a, Decl(constantEnumAssert.ts, 5, 9))

b = 'b'
>b : Symbol(E2.b, Decl(constantEnumAssert.ts, 6, 12))
}

enum E3 {
>E3 : Symbol(E3, Decl(constantEnumAssert.ts, 8, 1))

a = 1,
>a : Symbol(E3.a, Decl(constantEnumAssert.ts, 10, 9))

b = a << 1,
>b : Symbol(E3.b, Decl(constantEnumAssert.ts, 11, 10))
>a : Symbol(E3.a, Decl(constantEnumAssert.ts, 10, 9))

c = a << 2,
>c : Symbol(E3.c, Decl(constantEnumAssert.ts, 12, 15))
>a : Symbol(E3.a, Decl(constantEnumAssert.ts, 10, 9))
}

const enum E4 {
>E4 : Symbol(E4, Decl(constantEnumAssert.ts, 14, 1))

a,
>a : Symbol(E4.a, Decl(constantEnumAssert.ts, 16, 15))

b
>b : Symbol(E4.b, Decl(constantEnumAssert.ts, 17, 6))
}

const E5 = {
>E5 : Symbol(E5, Decl(constantEnumAssert.ts, 21, 5))

a: 'a',
>a : Symbol(a, Decl(constantEnumAssert.ts, 21, 12))

b: 'b'
>b : Symbol(b, Decl(constantEnumAssert.ts, 22, 11))
}

const foo1 = { a: E1.a }
>foo1 : Symbol(foo1, Decl(constantEnumAssert.ts, 26, 5))
>a : Symbol(a, Decl(constantEnumAssert.ts, 26, 14))
>E1.a : Symbol(E1.a, Decl(constantEnumAssert.ts, 0, 9))
>E1 : Symbol(E1, Decl(constantEnumAssert.ts, 0, 0))
>a : Symbol(E1.a, Decl(constantEnumAssert.ts, 0, 9))

const foo2 = { a: E2.a }
>foo2 : Symbol(foo2, Decl(constantEnumAssert.ts, 28, 5))
>a : Symbol(a, Decl(constantEnumAssert.ts, 28, 14))
>E2.a : Symbol(E2.a, Decl(constantEnumAssert.ts, 5, 9))
>E2 : Symbol(E2, Decl(constantEnumAssert.ts, 3, 1))
>a : Symbol(E2.a, Decl(constantEnumAssert.ts, 5, 9))

const foo3 = { a: E1.a } as const
>foo3 : Symbol(foo3, Decl(constantEnumAssert.ts, 30, 5))
>a : Symbol(a, Decl(constantEnumAssert.ts, 30, 14))
>E1.a : Symbol(E1.a, Decl(constantEnumAssert.ts, 0, 9))
>E1 : Symbol(E1, Decl(constantEnumAssert.ts, 0, 0))
>a : Symbol(E1.a, Decl(constantEnumAssert.ts, 0, 9))

const foo4 = { a: E2.a } as const
>foo4 : Symbol(foo4, Decl(constantEnumAssert.ts, 32, 5))
>a : Symbol(a, Decl(constantEnumAssert.ts, 32, 14))
>E2.a : Symbol(E2.a, Decl(constantEnumAssert.ts, 5, 9))
>E2 : Symbol(E2, Decl(constantEnumAssert.ts, 3, 1))
>a : Symbol(E2.a, Decl(constantEnumAssert.ts, 5, 9))

const foo5 = { a: E3.a } as const
>foo5 : Symbol(foo5, Decl(constantEnumAssert.ts, 34, 5))
>a : Symbol(a, Decl(constantEnumAssert.ts, 34, 14))
>E3.a : Symbol(E3.a, Decl(constantEnumAssert.ts, 10, 9))
>E3 : Symbol(E3, Decl(constantEnumAssert.ts, 8, 1))
>a : Symbol(E3.a, Decl(constantEnumAssert.ts, 10, 9))

const foo6 = { a: E4.a } as const
>foo6 : Symbol(foo6, Decl(constantEnumAssert.ts, 36, 5))
>a : Symbol(a, Decl(constantEnumAssert.ts, 36, 14))
>E4.a : Symbol(E4.a, Decl(constantEnumAssert.ts, 16, 15))
>E4 : Symbol(E4, Decl(constantEnumAssert.ts, 14, 1))
>a : Symbol(E4.a, Decl(constantEnumAssert.ts, 16, 15))

const foo7 = { a: E5.a } as const
>foo7 : Symbol(foo7, Decl(constantEnumAssert.ts, 38, 5))
>a : Symbol(a, Decl(constantEnumAssert.ts, 38, 14))
>E5.a : Symbol(a, Decl(constantEnumAssert.ts, 21, 12))
>E5 : Symbol(E5, Decl(constantEnumAssert.ts, 21, 5))
>a : Symbol(a, Decl(constantEnumAssert.ts, 21, 12))

const foo8 = { a: E1.a as const }
>foo8 : Symbol(foo8, Decl(constantEnumAssert.ts, 40, 5))
>a : Symbol(a, Decl(constantEnumAssert.ts, 40, 14))
>E1.a : Symbol(E1.a, Decl(constantEnumAssert.ts, 0, 9))
>E1 : Symbol(E1, Decl(constantEnumAssert.ts, 0, 0))
>a : Symbol(E1.a, Decl(constantEnumAssert.ts, 0, 9))

const foo9 = { a: E2.a as const }
>foo9 : Symbol(foo9, Decl(constantEnumAssert.ts, 42, 5))
>a : Symbol(a, Decl(constantEnumAssert.ts, 42, 14))
>E2.a : Symbol(E2.a, Decl(constantEnumAssert.ts, 5, 9))
>E2 : Symbol(E2, Decl(constantEnumAssert.ts, 3, 1))
>a : Symbol(E2.a, Decl(constantEnumAssert.ts, 5, 9))

const foo10 = { a: E3.a as const }
>foo10 : Symbol(foo10, Decl(constantEnumAssert.ts, 44, 5))
>a : Symbol(a, Decl(constantEnumAssert.ts, 44, 15))
>E3.a : Symbol(E3.a, Decl(constantEnumAssert.ts, 10, 9))
>E3 : Symbol(E3, Decl(constantEnumAssert.ts, 8, 1))
>a : Symbol(E3.a, Decl(constantEnumAssert.ts, 10, 9))

const foo11 = { a: E4.a as const }
>foo11 : Symbol(foo11, Decl(constantEnumAssert.ts, 46, 5))
>a : Symbol(a, Decl(constantEnumAssert.ts, 46, 15))
>E4.a : Symbol(E4.a, Decl(constantEnumAssert.ts, 16, 15))
>E4 : Symbol(E4, Decl(constantEnumAssert.ts, 14, 1))
>a : Symbol(E4.a, Decl(constantEnumAssert.ts, 16, 15))

const foo12 = { a: E5.a as const }
>foo12 : Symbol(foo12, Decl(constantEnumAssert.ts, 48, 5))
>a : Symbol(a, Decl(constantEnumAssert.ts, 48, 15))
>E5.a : Symbol(a, Decl(constantEnumAssert.ts, 21, 12))
>E5 : Symbol(E5, Decl(constantEnumAssert.ts, 21, 5))
>a : Symbol(a, Decl(constantEnumAssert.ts, 21, 12))

0 comments on commit bc46c77

Please sign in to comment.