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

Const contexts for literal expressions #29510

Merged
merged 6 commits into from
Jan 30, 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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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;
Loading