Skip to content
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

allow literan enum const assertions #30700

Merged
merged 3 commits into from Apr 25, 2019
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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))