Add readonly to TypeScript type modifier (#9529)

* add readonly to TSTypeOperator

* add more test cases for readonly
This commit is contained in:
Tan Li Hau 2019-03-16 13:41:52 +08:00 committed by Nicolò Ribaudo
parent 25a3825a1d
commit cc45608423
12 changed files with 306 additions and 9 deletions

View File

@ -741,14 +741,34 @@ export default (superClass: Class<Parser>): Class<Parser> =>
return type;
}
tsParseTypeOperator(operator: "keyof" | "unique"): N.TsTypeOperator {
tsParseTypeOperator(
operator: "keyof" | "unique" | "readonly",
): N.TsTypeOperator {
const node: N.TsTypeOperator = this.startNode();
this.expectContextual(operator);
node.operator = operator;
node.typeAnnotation = this.tsParseTypeOperatorOrHigher();
if (operator === "readonly") {
this.tsCheckTypeAnnotationForReadOnly(node);
}
return this.finishNode(node, "TSTypeOperator");
}
tsCheckTypeAnnotationForReadOnly(node: N.Node) {
switch (node.typeAnnotation.type) {
case "TSTupleType":
case "TSArrayType":
return;
default:
this.raise(
node.operator,
"'readonly' type modifier is only permitted on array and tuple literal types.",
);
}
}
tsParseInferType(): N.TsInferType {
const node = this.startNode();
this.expectContextual("infer");
@ -759,7 +779,9 @@ export default (superClass: Class<Parser>): Class<Parser> =>
}
tsParseTypeOperatorOrHigher(): N.TsType {
const operator = ["keyof", "unique"].find(kw => this.isContextual(kw));
const operator = ["keyof", "unique", "readonly"].find(kw =>
this.isContextual(kw),
);
return operator
? this.tsParseTypeOperator(operator)
: this.isContextual("infer")

View File

@ -1288,7 +1288,7 @@ export type TsParenthesizedType = TsTypeBase & {
export type TsTypeOperator = TsTypeBase & {
type: "TSTypeOperator",
operator: "keyof" | "unique",
operator: "keyof" | "unique" | "readonly",
typeAnnotation: TsType,
};

View File

@ -0,0 +1 @@
type T30 = readonly string; // Error

View File

@ -0,0 +1,7 @@
{
"sourceType": "module",
"plugins": [
"typescript"
],
"throws": "'readonly' type modifier is only permitted on array and tuple literal types. (1:NaN)"
}

View File

@ -0,0 +1 @@
type T31 = readonly T; // Error

View File

@ -0,0 +1,7 @@
{
"sourceType": "module",
"plugins": [
"typescript"
],
"throws": "'readonly' type modifier is only permitted on array and tuple literal types. (1:NaN)"
}

View File

@ -0,0 +1 @@
type T32 = readonly readonly string[]; // Error

View File

@ -0,0 +1,7 @@
{
"sourceType": "module",
"plugins": [
"typescript"
],
"throws": "'readonly' type modifier is only permitted on array and tuple literal types. (1:NaN)"
}

View File

@ -0,0 +1 @@
type T33 = readonly Array<string>; // Error

View File

@ -0,0 +1,7 @@
{
"sourceType": "module",
"plugins": [
"typescript"
],
"throws": "'readonly' type modifier is only permitted on array and tuple literal types. (1:NaN)"
}

View File

@ -1,2 +1,4 @@
let x: keyof T;
let y: unique symbol;
let z: readonly number[];
let z1: readonly [number, number];

View File

@ -1,29 +1,29 @@
{
"type": "File",
"start": 0,
"end": 37,
"end": 98,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 21
"line": 4,
"column": 34
}
},
"program": {
"type": "Program",
"start": 0,
"end": 37,
"end": 98,
"loc": {
"start": {
"line": 1,
"column": 0
},
"end": {
"line": 2,
"column": 21
"line": 4,
"column": 34
}
},
"sourceType": "module",
@ -239,6 +239,247 @@
}
],
"kind": "let"
},
{
"type": "VariableDeclaration",
"start": 38,
"end": 63,
"loc": {
"start": {
"line": 3,
"column": 0
},
"end": {
"line": 3,
"column": 25
}
},
"declarations": [
{
"type": "VariableDeclarator",
"start": 42,
"end": 62,
"loc": {
"start": {
"line": 3,
"column": 4
},
"end": {
"line": 3,
"column": 24
}
},
"id": {
"type": "Identifier",
"start": 42,
"end": 62,
"loc": {
"start": {
"line": 3,
"column": 4
},
"end": {
"line": 3,
"column": 24
},
"identifierName": "z"
},
"name": "z",
"typeAnnotation": {
"type": "TSTypeAnnotation",
"start": 43,
"end": 62,
"loc": {
"start": {
"line": 3,
"column": 5
},
"end": {
"line": 3,
"column": 24
}
},
"typeAnnotation": {
"type": "TSTypeOperator",
"start": 45,
"end": 62,
"loc": {
"start": {
"line": 3,
"column": 7
},
"end": {
"line": 3,
"column": 24
}
},
"operator": "readonly",
"typeAnnotation": {
"type": "TSArrayType",
"start": 54,
"end": 62,
"loc": {
"start": {
"line": 3,
"column": 16
},
"end": {
"line": 3,
"column": 24
}
},
"elementType": {
"type": "TSNumberKeyword",
"start": 54,
"end": 60,
"loc": {
"start": {
"line": 3,
"column": 16
},
"end": {
"line": 3,
"column": 22
}
}
}
}
}
}
},
"init": null
}
],
"kind": "let"
},
{
"type": "VariableDeclaration",
"start": 64,
"end": 98,
"loc": {
"start": {
"line": 4,
"column": 0
},
"end": {
"line": 4,
"column": 34
}
},
"declarations": [
{
"type": "VariableDeclarator",
"start": 68,
"end": 97,
"loc": {
"start": {
"line": 4,
"column": 4
},
"end": {
"line": 4,
"column": 33
}
},
"id": {
"type": "Identifier",
"start": 68,
"end": 97,
"loc": {
"start": {
"line": 4,
"column": 4
},
"end": {
"line": 4,
"column": 33
},
"identifierName": "z1"
},
"name": "z1",
"typeAnnotation": {
"type": "TSTypeAnnotation",
"start": 70,
"end": 97,
"loc": {
"start": {
"line": 4,
"column": 6
},
"end": {
"line": 4,
"column": 33
}
},
"typeAnnotation": {
"type": "TSTypeOperator",
"start": 72,
"end": 97,
"loc": {
"start": {
"line": 4,
"column": 8
},
"end": {
"line": 4,
"column": 33
}
},
"operator": "readonly",
"typeAnnotation": {
"type": "TSTupleType",
"start": 81,
"end": 97,
"loc": {
"start": {
"line": 4,
"column": 17
},
"end": {
"line": 4,
"column": 33
}
},
"elementTypes": [
{
"type": "TSNumberKeyword",
"start": 82,
"end": 88,
"loc": {
"start": {
"line": 4,
"column": 18
},
"end": {
"line": 4,
"column": 24
}
}
},
{
"type": "TSNumberKeyword",
"start": 90,
"end": 96,
"loc": {
"start": {
"line": 4,
"column": 26
},
"end": {
"line": 4,
"column": 32
}
}
}
]
}
}
}
},
"init": null
}
],
"kind": "let"
}
],
"directives": []