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; return type;
} }
tsParseTypeOperator(operator: "keyof" | "unique"): N.TsTypeOperator { tsParseTypeOperator(
operator: "keyof" | "unique" | "readonly",
): N.TsTypeOperator {
const node: N.TsTypeOperator = this.startNode(); const node: N.TsTypeOperator = this.startNode();
this.expectContextual(operator); this.expectContextual(operator);
node.operator = operator; node.operator = operator;
node.typeAnnotation = this.tsParseTypeOperatorOrHigher(); node.typeAnnotation = this.tsParseTypeOperatorOrHigher();
if (operator === "readonly") {
this.tsCheckTypeAnnotationForReadOnly(node);
}
return this.finishNode(node, "TSTypeOperator"); 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 { tsParseInferType(): N.TsInferType {
const node = this.startNode(); const node = this.startNode();
this.expectContextual("infer"); this.expectContextual("infer");
@ -759,7 +779,9 @@ export default (superClass: Class<Parser>): Class<Parser> =>
} }
tsParseTypeOperatorOrHigher(): N.TsType { tsParseTypeOperatorOrHigher(): N.TsType {
const operator = ["keyof", "unique"].find(kw => this.isContextual(kw)); const operator = ["keyof", "unique", "readonly"].find(kw =>
this.isContextual(kw),
);
return operator return operator
? this.tsParseTypeOperator(operator) ? this.tsParseTypeOperator(operator)
: this.isContextual("infer") : this.isContextual("infer")

View File

@ -1288,7 +1288,7 @@ export type TsParenthesizedType = TsTypeBase & {
export type TsTypeOperator = TsTypeBase & { export type TsTypeOperator = TsTypeBase & {
type: "TSTypeOperator", type: "TSTypeOperator",
operator: "keyof" | "unique", operator: "keyof" | "unique" | "readonly",
typeAnnotation: TsType, 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 x: keyof T;
let y: unique symbol; let y: unique symbol;
let z: readonly number[];
let z1: readonly [number, number];

View File

@ -1,29 +1,29 @@
{ {
"type": "File", "type": "File",
"start": 0, "start": 0,
"end": 37, "end": 98,
"loc": { "loc": {
"start": { "start": {
"line": 1, "line": 1,
"column": 0 "column": 0
}, },
"end": { "end": {
"line": 2, "line": 4,
"column": 21 "column": 34
} }
}, },
"program": { "program": {
"type": "Program", "type": "Program",
"start": 0, "start": 0,
"end": 37, "end": 98,
"loc": { "loc": {
"start": { "start": {
"line": 1, "line": 1,
"column": 0 "column": 0
}, },
"end": { "end": {
"line": 2, "line": 4,
"column": 21 "column": 34
} }
}, },
"sourceType": "module", "sourceType": "module",
@ -239,6 +239,247 @@
} }
], ],
"kind": "let" "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": [] "directives": []