Navigation Menu

Skip to content

Commit

Permalink
Merge pull request #29510 from Microsoft/constContexts
Browse files Browse the repository at this point in the history
Const contexts for literal expressions
  • Loading branch information
ahejlsberg committed Jan 30, 2019
2 parents eb513a2 + 08fe06f commit 96706a7
Show file tree
Hide file tree
Showing 10 changed files with 1,015 additions and 47 deletions.
128 changes: 81 additions & 47 deletions src/compiler/checker.ts

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions src/compiler/diagnosticMessages.json
Expand Up @@ -1027,6 +1027,10 @@
"category": "Error",
"code": 1354
},
"A 'const' assertion can only be applied to a string, number, boolean, array, or object literal.": {
"category": "Error",
"code": 1355
},

"Duplicate identifier '{0}'.": {
"category": "Error",
Expand Down
5 changes: 5 additions & 0 deletions src/compiler/utilities.ts
Expand Up @@ -5607,6 +5607,11 @@ namespace ts {
return node.kind === SyntaxKind.TypeAssertionExpression;
}

export function isConstTypeReference(node: Node) {
return isTypeReferenceNode(node) && isIdentifier(node.typeName) &&
node.typeName.escapedText === "const" && !node.typeArguments;
}

export function isParenthesizedExpression(node: Node): node is ParenthesizedExpression {
return node.kind === SyntaxKind.ParenthesizedExpression;
}
Expand Down
1 change: 1 addition & 0 deletions tests/baselines/reference/api/tsserverlibrary.d.ts
Expand Up @@ -3360,6 +3360,7 @@ declare namespace ts {
function isNewExpression(node: Node): node is NewExpression;
function isTaggedTemplateExpression(node: Node): node is TaggedTemplateExpression;
function isTypeAssertion(node: Node): node is TypeAssertion;
function isConstTypeReference(node: Node): boolean;
function isParenthesizedExpression(node: Node): node is ParenthesizedExpression;
function skipPartiallyEmittedExpressions(node: Expression): Expression;
function skipPartiallyEmittedExpressions(node: Node): Node;
Expand Down
1 change: 1 addition & 0 deletions tests/baselines/reference/api/typescript.d.ts
Expand Up @@ -3360,6 +3360,7 @@ declare namespace ts {
function isNewExpression(node: Node): node is NewExpression;
function isTaggedTemplateExpression(node: Node): node is TaggedTemplateExpression;
function isTypeAssertion(node: Node): node is TypeAssertion;
function isConstTypeReference(node: Node): boolean;
function isParenthesizedExpression(node: Node): node is ParenthesizedExpression;
function skipPartiallyEmittedExpressions(node: Expression): Expression;
function skipPartiallyEmittedExpressions(node: Node): Node;
Expand Down
79 changes: 79 additions & 0 deletions tests/baselines/reference/constAssertions.errors.txt
@@ -0,0 +1,79 @@
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 (4 errors) ====
let v1 = 'abc' as const;
let v2 = `abc` as const;
let v3 = 10 as const;
let v4 = -10 as const;
let v5 = +10 as const;
let v6 = 10n as const;
let v7 = -10n as const;
let v8 = true as const;
let v9 = false as const;

let c1 = 'abc' as const;
let c2 = `abc` as const;
let c3 = 10 as const;
let c4 = -10 as const;
let c5 = +10 as const;
let c6 = 10n as const;
let c7 = -10n as const;
let c8 = true as const;
let c9 = false as const;

let vv1 = v1;
let vc1 = c1;

let a1 = [] as const;
let a2 = [1, 2, 3] as const;
let a3 = [10, 'hello', true] as const;
let a4 = [...[1, 2, 3]] as const;
let a5 = [1, 2, 3];
let a6 = [...a5] as const;
let a7 = [...a6];
let a8 = ['abc', ...a7] as const;
let a9 = [...a8];

declare let d: { [x: string]: string };

let o1 = { x: 10, y: 20 } as const;
let o2 = { a: 1, 'b': 2, ['c']: 3, d() {}, ['e' + '']: 4 } as const;
let o3 = { ...o1, ...o2 } as const;
let o4 = { a: 1, b: 2 };
let o5 = { ...o4 } as const;
let o6 = { ...o5 };
let o7 = { ...d } as const;
let o8 = { ...o7 };
let o9 = { x: 10, foo() { this.x = 20 } } as const; // Error
~
!!! error TS2540: Cannot assign to 'x' because it is a read-only property.

let p1 = (10) as const;
let p2 = ((-10)) as const;
let p3 = ([(10)]) as const;
let p4 = [[[[10]]]] as const;

let x1 = { x: 10, y: [20, 30], z: { a: { b: 42 } } } as const;

let q1 = <const> 10;
let q2 = <const> 'abc';
let q3 = <const> true;
let q4 = <const> [1, 2, 3];
let q5 = <const> { x: 10, y: 20 };

declare function id<T>(x: T): T;

let e1 = v1 as const; // Error
~~
!!! error TS1355: A 'const' assertion can only be applied to a string, number, boolean, array, or object literal.
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.
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.

220 changes: 220 additions & 0 deletions tests/baselines/reference/constAssertions.js
@@ -0,0 +1,220 @@
//// [constAssertions.ts]
let v1 = 'abc' as const;
let v2 = `abc` as const;
let v3 = 10 as const;
let v4 = -10 as const;
let v5 = +10 as const;
let v6 = 10n as const;
let v7 = -10n as const;
let v8 = true as const;
let v9 = false as const;

let c1 = 'abc' as const;
let c2 = `abc` as const;
let c3 = 10 as const;
let c4 = -10 as const;
let c5 = +10 as const;
let c6 = 10n as const;
let c7 = -10n as const;
let c8 = true as const;
let c9 = false as const;

let vv1 = v1;
let vc1 = c1;

let a1 = [] as const;
let a2 = [1, 2, 3] as const;
let a3 = [10, 'hello', true] as const;
let a4 = [...[1, 2, 3]] as const;
let a5 = [1, 2, 3];
let a6 = [...a5] as const;
let a7 = [...a6];
let a8 = ['abc', ...a7] as const;
let a9 = [...a8];

declare let d: { [x: string]: string };

let o1 = { x: 10, y: 20 } as const;
let o2 = { a: 1, 'b': 2, ['c']: 3, d() {}, ['e' + '']: 4 } as const;
let o3 = { ...o1, ...o2 } as const;
let o4 = { a: 1, b: 2 };
let o5 = { ...o4 } as const;
let o6 = { ...o5 };
let o7 = { ...d } as const;
let o8 = { ...o7 };
let o9 = { x: 10, foo() { this.x = 20 } } as const; // Error

let p1 = (10) as const;
let p2 = ((-10)) as const;
let p3 = ([(10)]) as const;
let p4 = [[[[10]]]] as const;

let x1 = { x: 10, y: [20, 30], z: { a: { b: 42 } } } as const;

let q1 = <const> 10;
let q2 = <const> 'abc';
let q3 = <const> true;
let q4 = <const> [1, 2, 3];
let q5 = <const> { x: 10, y: 20 };

declare function id<T>(x: T): T;

let e1 = v1 as const; // Error
let e2 = (true ? 1 : 0) as const; // Error
let e3 = id(1) as const; // Error


//// [constAssertions.js]
"use strict";
let v1 = 'abc';
let v2 = `abc`;
let v3 = 10;
let v4 = -10;
let v5 = +10;
let v6 = 10n;
let v7 = -10n;
let v8 = true;
let v9 = false;
let c1 = 'abc';
let c2 = `abc`;
let c3 = 10;
let c4 = -10;
let c5 = +10;
let c6 = 10n;
let c7 = -10n;
let c8 = true;
let c9 = false;
let vv1 = v1;
let vc1 = c1;
let a1 = [];
let a2 = [1, 2, 3];
let a3 = [10, 'hello', true];
let a4 = [...[1, 2, 3]];
let a5 = [1, 2, 3];
let a6 = [...a5];
let a7 = [...a6];
let a8 = ['abc', ...a7];
let a9 = [...a8];
let o1 = { x: 10, y: 20 };
let o2 = { a: 1, 'b': 2, ['c']: 3, d() { }, ['e' + '']: 4 };
let o3 = { ...o1, ...o2 };
let o4 = { a: 1, b: 2 };
let o5 = { ...o4 };
let o6 = { ...o5 };
let o7 = { ...d };
let o8 = { ...o7 };
let o9 = { x: 10, foo() { this.x = 20; } }; // Error
let p1 = (10);
let p2 = ((-10));
let p3 = ([(10)]);
let p4 = [[[[10]]]];
let x1 = { x: 10, y: [20, 30], z: { a: { b: 42 } } };
let q1 = 10;
let q2 = 'abc';
let q3 = true;
let q4 = [1, 2, 3];
let q5 = { x: 10, y: 20 };
let e1 = v1; // Error
let e2 = (true ? 1 : 0); // Error
let e3 = id(1); // Error


//// [constAssertions.d.ts]
declare let v1: "abc";
declare let v2: "abc";
declare let v3: 10;
declare let v4: -10;
declare let v5: 10;
declare let v6: 10n;
declare let v7: -10n;
declare let v8: true;
declare let v9: false;
declare let c1: "abc";
declare let c2: "abc";
declare let c3: 10;
declare let c4: -10;
declare let c5: 10;
declare let c6: 10n;
declare let c7: -10n;
declare let c8: true;
declare let c9: false;
declare let vv1: "abc";
declare let vc1: "abc";
declare let a1: readonly [];
declare let a2: readonly [1, 2, 3];
declare let a3: readonly [10, "hello", true];
declare let a4: readonly (1 | 2 | 3)[];
declare let a5: number[];
declare let a6: readonly number[];
declare let a7: number[];
declare let a8: readonly ["abc", ...number[]];
declare let a9: (number | "abc")[];
declare let d: {
[x: string]: string;
};
declare let o1: {
readonly x: 10;
readonly y: 20;
};
declare let o2: {
readonly [x: string]: 1 | 2 | 3 | (() => void) | 4;
readonly a: 1;
readonly 'b': 2;
readonly ['c']: 3;
readonly d: () => void;
};
declare let o3: {
readonly a: 1;
readonly 'b': 2;
readonly ['c']: 3;
readonly d: () => void;
readonly x: 10;
readonly y: 20;
};
declare let o4: {
a: number;
b: number;
};
declare let o5: {
readonly a: number;
readonly b: number;
};
declare let o6: {
a: number;
b: number;
};
declare let o7: {
readonly [x: string]: string;
};
declare let o8: {
[x: string]: string;
};
declare let o9: {
readonly x: 10;
readonly foo: () => void;
};
declare let p1: 10;
declare let p2: -10;
declare let p3: readonly [10];
declare let p4: readonly [readonly [readonly [readonly [10]]]];
declare let x1: {
readonly x: 10;
readonly y: readonly [20, 30];
z: {
a: {
readonly b: 42;
};
};
};
declare let q1: 10;
declare let q2: "abc";
declare let q3: true;
declare let q4: readonly [1, 2, 3];
declare let q5: {
readonly x: 10;
readonly y: 20;
};
declare function id<T>(x: T): T;
declare let e1: "abc";
declare let e2: 0 | 1;
declare let e3: 1;

0 comments on commit 96706a7

Please sign in to comment.