TypeScript 4.0: Support labeled tuple elements (#11754)
* TypeScript 4.0: Support labeled tuple elements * More tests * Disallow mixing labeled and unlabeled elements * Update AST shape * Enable test after rebase * Allow labeled spread types * Fix flow * Add types and generator suport * Update packages/babel-parser/src/plugins/typescript/index.js * Prettier
This commit is contained in:
parent
9e6663f125
commit
eba4c3b6ed
@ -262,6 +262,14 @@ export function TSRestType(node) {
|
||||
this.print(node.typeAnnotation, node);
|
||||
}
|
||||
|
||||
export function TSNamedTupleMember(node) {
|
||||
this.print(node.label, node);
|
||||
if (node.optional) this.token("?");
|
||||
this.token(":");
|
||||
this.space();
|
||||
this.print(node.elementType, node);
|
||||
}
|
||||
|
||||
export function TSUnionType(node) {
|
||||
this.tsPrintUnionOrIntersectionType(node, "|");
|
||||
}
|
||||
|
||||
1
packages/babel-generator/test/fixtures/typescript/tuple-labeled/input.js
vendored
Normal file
1
packages/babel-generator/test/fixtures/typescript/tuple-labeled/input.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
type T = [x: A, y?: B, ...z: C];
|
||||
1
packages/babel-generator/test/fixtures/typescript/tuple-labeled/output.js
vendored
Normal file
1
packages/babel-generator/test/fixtures/typescript/tuple-labeled/output.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
type T = [x: A, y?: B, ...z: C];
|
||||
@ -74,6 +74,10 @@ const TSErrors = Object.freeze({
|
||||
IndexSignatureHasAccessibility:
|
||||
"Index signatures cannot have an accessibility modifier ('%0')",
|
||||
IndexSignatureHasStatic: "Index signatures cannot have the 'static' modifier",
|
||||
InvalidTupleMemberLabel:
|
||||
"Tuple members must be labeled with a simple identifier.",
|
||||
MixedLabeledAndUnlabeledElements:
|
||||
"Tuple members must all have names or all not have names.",
|
||||
OptionalTypeBeforeRequired:
|
||||
"A required element cannot follow an optional element.",
|
||||
PatternIsOptional:
|
||||
@ -633,33 +637,87 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
// Validate the elementTypes to ensure that no mandatory elements
|
||||
// follow optional elements
|
||||
let seenOptionalElement = false;
|
||||
let labeledElements = null;
|
||||
node.elementTypes.forEach(elementNode => {
|
||||
if (elementNode.type === "TSOptionalType") {
|
||||
seenOptionalElement = true;
|
||||
} else if (seenOptionalElement && elementNode.type !== "TSRestType") {
|
||||
let { type } = elementNode;
|
||||
|
||||
if (
|
||||
seenOptionalElement &&
|
||||
type !== "TSRestType" &&
|
||||
type !== "TSOptionalType" &&
|
||||
!(type === "TSNamedTupleMember" && elementNode.optional)
|
||||
) {
|
||||
this.raise(elementNode.start, TSErrors.OptionalTypeBeforeRequired);
|
||||
}
|
||||
|
||||
// Flow doesn't support ||=
|
||||
seenOptionalElement =
|
||||
seenOptionalElement ||
|
||||
(type === "TSNamedTupleMember" && elementNode.optional) ||
|
||||
type === "TSOptionalType";
|
||||
|
||||
// When checking labels, check the argument of the spread operator
|
||||
if (type === "TSRestType") {
|
||||
elementNode = elementNode.typeAnnotation;
|
||||
type = elementNode.type;
|
||||
}
|
||||
|
||||
const isLabeled = type === "TSNamedTupleMember";
|
||||
// Flow doesn't support ??=
|
||||
labeledElements = labeledElements ?? isLabeled;
|
||||
if (labeledElements !== isLabeled) {
|
||||
this.raise(
|
||||
elementNode.start,
|
||||
TSErrors.MixedLabeledAndUnlabeledElements,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
return this.finishNode(node, "TSTupleType");
|
||||
}
|
||||
|
||||
tsParseTupleElementType(): N.TsType {
|
||||
tsParseTupleElementType(): N.TsType | N.TsNamedTupleMember {
|
||||
// parses `...TsType[]`
|
||||
if (this.match(tt.ellipsis)) {
|
||||
const restNode: N.TsRestType = this.startNode();
|
||||
this.next(); // skips ellipsis
|
||||
restNode.typeAnnotation = this.tsParseType();
|
||||
return this.finishNode(restNode, "TSRestType");
|
||||
|
||||
const { start: startPos, startLoc } = this.state;
|
||||
|
||||
const rest = this.eat(tt.ellipsis);
|
||||
let type = this.tsParseType();
|
||||
const optional = this.eat(tt.question);
|
||||
const labeled = this.eat(tt.colon);
|
||||
|
||||
if (labeled) {
|
||||
const labeledNode: N.TsNamedTupleMember = this.startNodeAtNode(type);
|
||||
labeledNode.optional = optional;
|
||||
|
||||
if (
|
||||
type.type === "TSTypeReference" &&
|
||||
!type.typeParameters &&
|
||||
type.typeName.type === "Identifier"
|
||||
) {
|
||||
labeledNode.label = (type.typeName: N.Identifier);
|
||||
} else {
|
||||
this.raise(type.start, TSErrors.InvalidTupleMemberLabel);
|
||||
// This produces an invalid AST, but at least we don't drop
|
||||
// nodes representing the invalid source.
|
||||
// $FlowIgnore
|
||||
labeledNode.label = type;
|
||||
}
|
||||
|
||||
const type = this.tsParseType();
|
||||
// parses `TsType?`
|
||||
if (this.eat(tt.question)) {
|
||||
labeledNode.elementType = this.tsParseType();
|
||||
type = this.finishNode(labeledNode, "TSNamedTupleMember");
|
||||
} else if (optional) {
|
||||
const optionalTypeNode: N.TsOptionalType = this.startNodeAtNode(type);
|
||||
optionalTypeNode.typeAnnotation = type;
|
||||
return this.finishNode(optionalTypeNode, "TSOptionalType");
|
||||
type = this.finishNode(optionalTypeNode, "TSOptionalType");
|
||||
}
|
||||
|
||||
if (rest) {
|
||||
const restNode: N.TsRestType = this.startNodeAt(startPos, startLoc);
|
||||
restNode.typeAnnotation = type;
|
||||
type = this.finishNode(restNode, "TSRestType");
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
|
||||
@ -1264,7 +1264,14 @@ export type TsArrayType = TsTypeBase & {
|
||||
|
||||
export type TsTupleType = TsTypeBase & {
|
||||
type: "TSTupleType",
|
||||
elementTypes: $ReadOnlyArray<TsType>,
|
||||
elementTypes: $ReadOnlyArray<TsType | TsNamedTupleMember>,
|
||||
};
|
||||
|
||||
export type TsNamedTupleMember = NodeBase & {
|
||||
type: "TSNamedTupleMember",
|
||||
label: Identifier,
|
||||
optional: boolean,
|
||||
elementType: TsType,
|
||||
};
|
||||
|
||||
export type TsOptionalType = TsTypeBase & {
|
||||
@ -1274,7 +1281,7 @@ export type TsOptionalType = TsTypeBase & {
|
||||
|
||||
export type TsRestType = TsTypeBase & {
|
||||
type: "TSRestType",
|
||||
typeAnnotation: TsType,
|
||||
typeAnnotation: TsType | TsNamedTupleMember,
|
||||
};
|
||||
|
||||
export type TsUnionOrIntersectionType = TsUnionType | TsIntersectionType;
|
||||
|
||||
1
packages/babel-parser/test/fixtures/typescript/types/tuple-invalid-label-1/input.ts
vendored
Normal file
1
packages/babel-parser/test/fixtures/typescript/types/tuple-invalid-label-1/input.ts
vendored
Normal file
@ -0,0 +1 @@
|
||||
type T = [x.y: A];
|
||||
6
packages/babel-parser/test/fixtures/typescript/types/tuple-invalid-label-1/options.json
vendored
Normal file
6
packages/babel-parser/test/fixtures/typescript/types/tuple-invalid-label-1/options.json
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"sourceType": "module",
|
||||
"plugins": [
|
||||
"typescript"
|
||||
]
|
||||
}
|
||||
63
packages/babel-parser/test/fixtures/typescript/types/tuple-invalid-label-1/output.json
vendored
Normal file
63
packages/babel-parser/test/fixtures/typescript/types/tuple-invalid-label-1/output.json
vendored
Normal file
@ -0,0 +1,63 @@
|
||||
{
|
||||
"type": "File",
|
||||
"start":0,"end":18,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":18}},
|
||||
"errors": [
|
||||
"SyntaxError: Tuple members must be labeled with a simple identifier. (1:10)"
|
||||
],
|
||||
"program": {
|
||||
"type": "Program",
|
||||
"start":0,"end":18,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":18}},
|
||||
"sourceType": "module",
|
||||
"interpreter": null,
|
||||
"body": [
|
||||
{
|
||||
"type": "TSTypeAliasDeclaration",
|
||||
"start":0,"end":18,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":18}},
|
||||
"id": {
|
||||
"type": "Identifier",
|
||||
"start":5,"end":6,"loc":{"start":{"line":1,"column":5},"end":{"line":1,"column":6},"identifierName":"T"},
|
||||
"name": "T"
|
||||
},
|
||||
"typeAnnotation": {
|
||||
"type": "TSTupleType",
|
||||
"start":9,"end":17,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":17}},
|
||||
"elementTypes": [
|
||||
{
|
||||
"type": "TSNamedTupleMember",
|
||||
"start":10,"end":16,"loc":{"start":{"line":1,"column":10},"end":{"line":1,"column":16}},
|
||||
"optional": false,
|
||||
"label": {
|
||||
"type": "TSTypeReference",
|
||||
"start":10,"end":13,"loc":{"start":{"line":1,"column":10},"end":{"line":1,"column":13}},
|
||||
"typeName": {
|
||||
"type": "TSQualifiedName",
|
||||
"start":10,"end":13,"loc":{"start":{"line":1,"column":10},"end":{"line":1,"column":13}},
|
||||
"left": {
|
||||
"type": "Identifier",
|
||||
"start":10,"end":11,"loc":{"start":{"line":1,"column":10},"end":{"line":1,"column":11},"identifierName":"x"},
|
||||
"name": "x"
|
||||
},
|
||||
"right": {
|
||||
"type": "Identifier",
|
||||
"start":12,"end":13,"loc":{"start":{"line":1,"column":12},"end":{"line":1,"column":13},"identifierName":"y"},
|
||||
"name": "y"
|
||||
}
|
||||
}
|
||||
},
|
||||
"elementType": {
|
||||
"type": "TSTypeReference",
|
||||
"start":15,"end":16,"loc":{"start":{"line":1,"column":15},"end":{"line":1,"column":16}},
|
||||
"typeName": {
|
||||
"type": "Identifier",
|
||||
"start":15,"end":16,"loc":{"start":{"line":1,"column":15},"end":{"line":1,"column":16},"identifierName":"A"},
|
||||
"name": "A"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"directives": []
|
||||
}
|
||||
}
|
||||
1
packages/babel-parser/test/fixtures/typescript/types/tuple-invalid-label-2/input.ts
vendored
Normal file
1
packages/babel-parser/test/fixtures/typescript/types/tuple-invalid-label-2/input.ts
vendored
Normal file
@ -0,0 +1 @@
|
||||
type T = [x<y>: A];
|
||||
6
packages/babel-parser/test/fixtures/typescript/types/tuple-invalid-label-2/options.json
vendored
Normal file
6
packages/babel-parser/test/fixtures/typescript/types/tuple-invalid-label-2/options.json
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"sourceType": "module",
|
||||
"plugins": [
|
||||
"typescript"
|
||||
]
|
||||
}
|
||||
69
packages/babel-parser/test/fixtures/typescript/types/tuple-invalid-label-2/output.json
vendored
Normal file
69
packages/babel-parser/test/fixtures/typescript/types/tuple-invalid-label-2/output.json
vendored
Normal file
@ -0,0 +1,69 @@
|
||||
{
|
||||
"type": "File",
|
||||
"start":0,"end":19,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":19}},
|
||||
"errors": [
|
||||
"SyntaxError: Tuple members must be labeled with a simple identifier. (1:10)"
|
||||
],
|
||||
"program": {
|
||||
"type": "Program",
|
||||
"start":0,"end":19,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":19}},
|
||||
"sourceType": "module",
|
||||
"interpreter": null,
|
||||
"body": [
|
||||
{
|
||||
"type": "TSTypeAliasDeclaration",
|
||||
"start":0,"end":19,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":19}},
|
||||
"id": {
|
||||
"type": "Identifier",
|
||||
"start":5,"end":6,"loc":{"start":{"line":1,"column":5},"end":{"line":1,"column":6},"identifierName":"T"},
|
||||
"name": "T"
|
||||
},
|
||||
"typeAnnotation": {
|
||||
"type": "TSTupleType",
|
||||
"start":9,"end":18,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":18}},
|
||||
"elementTypes": [
|
||||
{
|
||||
"type": "TSNamedTupleMember",
|
||||
"start":10,"end":17,"loc":{"start":{"line":1,"column":10},"end":{"line":1,"column":17}},
|
||||
"optional": false,
|
||||
"label": {
|
||||
"type": "TSTypeReference",
|
||||
"start":10,"end":14,"loc":{"start":{"line":1,"column":10},"end":{"line":1,"column":14}},
|
||||
"typeName": {
|
||||
"type": "Identifier",
|
||||
"start":10,"end":11,"loc":{"start":{"line":1,"column":10},"end":{"line":1,"column":11},"identifierName":"x"},
|
||||
"name": "x"
|
||||
},
|
||||
"typeParameters": {
|
||||
"type": "TSTypeParameterInstantiation",
|
||||
"start":11,"end":14,"loc":{"start":{"line":1,"column":11},"end":{"line":1,"column":14}},
|
||||
"params": [
|
||||
{
|
||||
"type": "TSTypeReference",
|
||||
"start":12,"end":13,"loc":{"start":{"line":1,"column":12},"end":{"line":1,"column":13}},
|
||||
"typeName": {
|
||||
"type": "Identifier",
|
||||
"start":12,"end":13,"loc":{"start":{"line":1,"column":12},"end":{"line":1,"column":13},"identifierName":"y"},
|
||||
"name": "y"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"elementType": {
|
||||
"type": "TSTypeReference",
|
||||
"start":16,"end":17,"loc":{"start":{"line":1,"column":16},"end":{"line":1,"column":17}},
|
||||
"typeName": {
|
||||
"type": "Identifier",
|
||||
"start":16,"end":17,"loc":{"start":{"line":1,"column":16},"end":{"line":1,"column":17},"identifierName":"A"},
|
||||
"name": "A"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"directives": []
|
||||
}
|
||||
}
|
||||
1
packages/babel-parser/test/fixtures/typescript/types/tuple-labeled-after-unlabeled/input.ts
vendored
Normal file
1
packages/babel-parser/test/fixtures/typescript/types/tuple-labeled-after-unlabeled/input.ts
vendored
Normal file
@ -0,0 +1 @@
|
||||
type T = [A, y: B];
|
||||
59
packages/babel-parser/test/fixtures/typescript/types/tuple-labeled-after-unlabeled/output.json
vendored
Normal file
59
packages/babel-parser/test/fixtures/typescript/types/tuple-labeled-after-unlabeled/output.json
vendored
Normal file
@ -0,0 +1,59 @@
|
||||
{
|
||||
"type": "File",
|
||||
"start":0,"end":19,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":19}},
|
||||
"errors": [
|
||||
"SyntaxError: Tuple members must all have names or all not have names. (1:13)"
|
||||
],
|
||||
"program": {
|
||||
"type": "Program",
|
||||
"start":0,"end":19,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":19}},
|
||||
"sourceType": "module",
|
||||
"interpreter": null,
|
||||
"body": [
|
||||
{
|
||||
"type": "TSTypeAliasDeclaration",
|
||||
"start":0,"end":19,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":19}},
|
||||
"id": {
|
||||
"type": "Identifier",
|
||||
"start":5,"end":6,"loc":{"start":{"line":1,"column":5},"end":{"line":1,"column":6},"identifierName":"T"},
|
||||
"name": "T"
|
||||
},
|
||||
"typeAnnotation": {
|
||||
"type": "TSTupleType",
|
||||
"start":9,"end":18,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":18}},
|
||||
"elementTypes": [
|
||||
{
|
||||
"type": "TSTypeReference",
|
||||
"start":10,"end":11,"loc":{"start":{"line":1,"column":10},"end":{"line":1,"column":11}},
|
||||
"typeName": {
|
||||
"type": "Identifier",
|
||||
"start":10,"end":11,"loc":{"start":{"line":1,"column":10},"end":{"line":1,"column":11},"identifierName":"A"},
|
||||
"name": "A"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "TSNamedTupleMember",
|
||||
"start":13,"end":17,"loc":{"start":{"line":1,"column":13},"end":{"line":1,"column":17}},
|
||||
"optional": false,
|
||||
"label": {
|
||||
"type": "Identifier",
|
||||
"start":13,"end":14,"loc":{"start":{"line":1,"column":13},"end":{"line":1,"column":14},"identifierName":"y"},
|
||||
"name": "y"
|
||||
},
|
||||
"elementType": {
|
||||
"type": "TSTypeReference",
|
||||
"start":16,"end":17,"loc":{"start":{"line":1,"column":16},"end":{"line":1,"column":17}},
|
||||
"typeName": {
|
||||
"type": "Identifier",
|
||||
"start":16,"end":17,"loc":{"start":{"line":1,"column":16},"end":{"line":1,"column":17},"identifierName":"B"},
|
||||
"name": "B"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"directives": []
|
||||
}
|
||||
}
|
||||
1
packages/babel-parser/test/fixtures/typescript/types/tuple-labeled-before-unlabeled/input.ts
vendored
Normal file
1
packages/babel-parser/test/fixtures/typescript/types/tuple-labeled-before-unlabeled/input.ts
vendored
Normal file
@ -0,0 +1 @@
|
||||
type T = [x: A, B];
|
||||
59
packages/babel-parser/test/fixtures/typescript/types/tuple-labeled-before-unlabeled/output.json
vendored
Normal file
59
packages/babel-parser/test/fixtures/typescript/types/tuple-labeled-before-unlabeled/output.json
vendored
Normal file
@ -0,0 +1,59 @@
|
||||
{
|
||||
"type": "File",
|
||||
"start":0,"end":19,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":19}},
|
||||
"errors": [
|
||||
"SyntaxError: Tuple members must all have names or all not have names. (1:16)"
|
||||
],
|
||||
"program": {
|
||||
"type": "Program",
|
||||
"start":0,"end":19,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":19}},
|
||||
"sourceType": "module",
|
||||
"interpreter": null,
|
||||
"body": [
|
||||
{
|
||||
"type": "TSTypeAliasDeclaration",
|
||||
"start":0,"end":19,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":19}},
|
||||
"id": {
|
||||
"type": "Identifier",
|
||||
"start":5,"end":6,"loc":{"start":{"line":1,"column":5},"end":{"line":1,"column":6},"identifierName":"T"},
|
||||
"name": "T"
|
||||
},
|
||||
"typeAnnotation": {
|
||||
"type": "TSTupleType",
|
||||
"start":9,"end":18,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":18}},
|
||||
"elementTypes": [
|
||||
{
|
||||
"type": "TSNamedTupleMember",
|
||||
"start":10,"end":14,"loc":{"start":{"line":1,"column":10},"end":{"line":1,"column":14}},
|
||||
"optional": false,
|
||||
"label": {
|
||||
"type": "Identifier",
|
||||
"start":10,"end":11,"loc":{"start":{"line":1,"column":10},"end":{"line":1,"column":11},"identifierName":"x"},
|
||||
"name": "x"
|
||||
},
|
||||
"elementType": {
|
||||
"type": "TSTypeReference",
|
||||
"start":13,"end":14,"loc":{"start":{"line":1,"column":13},"end":{"line":1,"column":14}},
|
||||
"typeName": {
|
||||
"type": "Identifier",
|
||||
"start":13,"end":14,"loc":{"start":{"line":1,"column":13},"end":{"line":1,"column":14},"identifierName":"A"},
|
||||
"name": "A"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "TSTypeReference",
|
||||
"start":16,"end":17,"loc":{"start":{"line":1,"column":16},"end":{"line":1,"column":17}},
|
||||
"typeName": {
|
||||
"type": "Identifier",
|
||||
"start":16,"end":17,"loc":{"start":{"line":1,"column":16},"end":{"line":1,"column":17},"identifierName":"B"},
|
||||
"name": "B"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"directives": []
|
||||
}
|
||||
}
|
||||
1
packages/babel-parser/test/fixtures/typescript/types/tuple-labeled-invalid-optional/input.ts
vendored
Normal file
1
packages/babel-parser/test/fixtures/typescript/types/tuple-labeled-invalid-optional/input.ts
vendored
Normal file
@ -0,0 +1 @@
|
||||
type T = [x: A?];
|
||||
@ -0,0 +1,7 @@
|
||||
{
|
||||
"sourceType": "module",
|
||||
"plugins": [
|
||||
"typescript"
|
||||
],
|
||||
"throws": "Unexpected token, expected \",\" (1:14)"
|
||||
}
|
||||
1
packages/babel-parser/test/fixtures/typescript/types/tuple-labeled-spread/input.ts
vendored
Normal file
1
packages/babel-parser/test/fixtures/typescript/types/tuple-labeled-spread/input.ts
vendored
Normal file
@ -0,0 +1 @@
|
||||
let x: [A: string, ...B: number[]]
|
||||
76
packages/babel-parser/test/fixtures/typescript/types/tuple-labeled-spread/output.json
vendored
Normal file
76
packages/babel-parser/test/fixtures/typescript/types/tuple-labeled-spread/output.json
vendored
Normal file
@ -0,0 +1,76 @@
|
||||
{
|
||||
"type": "File",
|
||||
"start":0,"end":34,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":34}},
|
||||
"program": {
|
||||
"type": "Program",
|
||||
"start":0,"end":34,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":34}},
|
||||
"sourceType": "module",
|
||||
"interpreter": null,
|
||||
"body": [
|
||||
{
|
||||
"type": "VariableDeclaration",
|
||||
"start":0,"end":34,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":34}},
|
||||
"declarations": [
|
||||
{
|
||||
"type": "VariableDeclarator",
|
||||
"start":4,"end":34,"loc":{"start":{"line":1,"column":4},"end":{"line":1,"column":34}},
|
||||
"id": {
|
||||
"type": "Identifier",
|
||||
"start":4,"end":34,"loc":{"start":{"line":1,"column":4},"end":{"line":1,"column":34},"identifierName":"x"},
|
||||
"name": "x",
|
||||
"typeAnnotation": {
|
||||
"type": "TSTypeAnnotation",
|
||||
"start":5,"end":34,"loc":{"start":{"line":1,"column":5},"end":{"line":1,"column":34}},
|
||||
"typeAnnotation": {
|
||||
"type": "TSTupleType",
|
||||
"start":7,"end":34,"loc":{"start":{"line":1,"column":7},"end":{"line":1,"column":34}},
|
||||
"elementTypes": [
|
||||
{
|
||||
"type": "TSNamedTupleMember",
|
||||
"start":8,"end":17,"loc":{"start":{"line":1,"column":8},"end":{"line":1,"column":17}},
|
||||
"optional": false,
|
||||
"label": {
|
||||
"type": "Identifier",
|
||||
"start":8,"end":9,"loc":{"start":{"line":1,"column":8},"end":{"line":1,"column":9},"identifierName":"A"},
|
||||
"name": "A"
|
||||
},
|
||||
"elementType": {
|
||||
"type": "TSStringKeyword",
|
||||
"start":11,"end":17,"loc":{"start":{"line":1,"column":11},"end":{"line":1,"column":17}}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "TSRestType",
|
||||
"start":19,"end":33,"loc":{"start":{"line":1,"column":19},"end":{"line":1,"column":33}},
|
||||
"typeAnnotation": {
|
||||
"type": "TSNamedTupleMember",
|
||||
"start":22,"end":33,"loc":{"start":{"line":1,"column":22},"end":{"line":1,"column":33}},
|
||||
"optional": false,
|
||||
"label": {
|
||||
"type": "Identifier",
|
||||
"start":22,"end":23,"loc":{"start":{"line":1,"column":22},"end":{"line":1,"column":23},"identifierName":"B"},
|
||||
"name": "B"
|
||||
},
|
||||
"elementType": {
|
||||
"type": "TSArrayType",
|
||||
"start":25,"end":33,"loc":{"start":{"line":1,"column":25},"end":{"line":1,"column":33}},
|
||||
"elementType": {
|
||||
"type": "TSNumberKeyword",
|
||||
"start":25,"end":31,"loc":{"start":{"line":1,"column":25},"end":{"line":1,"column":31}}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"init": null
|
||||
}
|
||||
],
|
||||
"kind": "let"
|
||||
}
|
||||
],
|
||||
"directives": []
|
||||
}
|
||||
}
|
||||
1
packages/babel-parser/test/fixtures/typescript/types/tuple-labeled/input.ts
vendored
Normal file
1
packages/babel-parser/test/fixtures/typescript/types/tuple-labeled/input.ts
vendored
Normal file
@ -0,0 +1 @@
|
||||
type T = [foo: string, bar?: number];
|
||||
56
packages/babel-parser/test/fixtures/typescript/types/tuple-labeled/output.json
vendored
Normal file
56
packages/babel-parser/test/fixtures/typescript/types/tuple-labeled/output.json
vendored
Normal file
@ -0,0 +1,56 @@
|
||||
{
|
||||
"type": "File",
|
||||
"start":0,"end":37,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":37}},
|
||||
"program": {
|
||||
"type": "Program",
|
||||
"start":0,"end":37,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":37}},
|
||||
"sourceType": "module",
|
||||
"interpreter": null,
|
||||
"body": [
|
||||
{
|
||||
"type": "TSTypeAliasDeclaration",
|
||||
"start":0,"end":37,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":37}},
|
||||
"id": {
|
||||
"type": "Identifier",
|
||||
"start":5,"end":6,"loc":{"start":{"line":1,"column":5},"end":{"line":1,"column":6},"identifierName":"T"},
|
||||
"name": "T"
|
||||
},
|
||||
"typeAnnotation": {
|
||||
"type": "TSTupleType",
|
||||
"start":9,"end":36,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":36}},
|
||||
"elementTypes": [
|
||||
{
|
||||
"type": "TSNamedTupleMember",
|
||||
"start":10,"end":21,"loc":{"start":{"line":1,"column":10},"end":{"line":1,"column":21}},
|
||||
"optional": false,
|
||||
"label": {
|
||||
"type": "Identifier",
|
||||
"start":10,"end":13,"loc":{"start":{"line":1,"column":10},"end":{"line":1,"column":13},"identifierName":"foo"},
|
||||
"name": "foo"
|
||||
},
|
||||
"elementType": {
|
||||
"type": "TSStringKeyword",
|
||||
"start":15,"end":21,"loc":{"start":{"line":1,"column":15},"end":{"line":1,"column":21}}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "TSNamedTupleMember",
|
||||
"start":23,"end":35,"loc":{"start":{"line":1,"column":23},"end":{"line":1,"column":35}},
|
||||
"optional": true,
|
||||
"label": {
|
||||
"type": "Identifier",
|
||||
"start":23,"end":26,"loc":{"start":{"line":1,"column":23},"end":{"line":1,"column":26},"identifierName":"bar"},
|
||||
"name": "bar"
|
||||
},
|
||||
"elementType": {
|
||||
"type": "TSNumberKeyword",
|
||||
"start":29,"end":35,"loc":{"start":{"line":1,"column":29},"end":{"line":1,"column":35}}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"directives": []
|
||||
}
|
||||
}
|
||||
@ -0,0 +1 @@
|
||||
type T = [x?: A, y: B];
|
||||
@ -0,0 +1,69 @@
|
||||
{
|
||||
"type": "File",
|
||||
"start":0,"end":23,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":23}},
|
||||
"errors": [
|
||||
"SyntaxError: A required element cannot follow an optional element. (1:17)"
|
||||
],
|
||||
"program": {
|
||||
"type": "Program",
|
||||
"start":0,"end":23,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":23}},
|
||||
"sourceType": "module",
|
||||
"interpreter": null,
|
||||
"body": [
|
||||
{
|
||||
"type": "TSTypeAliasDeclaration",
|
||||
"start":0,"end":23,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":23}},
|
||||
"id": {
|
||||
"type": "Identifier",
|
||||
"start":5,"end":6,"loc":{"start":{"line":1,"column":5},"end":{"line":1,"column":6},"identifierName":"T"},
|
||||
"name": "T"
|
||||
},
|
||||
"typeAnnotation": {
|
||||
"type": "TSTupleType",
|
||||
"start":9,"end":22,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":22}},
|
||||
"elementTypes": [
|
||||
{
|
||||
"type": "TSNamedTupleMember",
|
||||
"start":10,"end":15,"loc":{"start":{"line":1,"column":10},"end":{"line":1,"column":15}},
|
||||
"optional": true,
|
||||
"label": {
|
||||
"type": "Identifier",
|
||||
"start":10,"end":11,"loc":{"start":{"line":1,"column":10},"end":{"line":1,"column":11},"identifierName":"x"},
|
||||
"name": "x"
|
||||
},
|
||||
"elementType": {
|
||||
"type": "TSTypeReference",
|
||||
"start":14,"end":15,"loc":{"start":{"line":1,"column":14},"end":{"line":1,"column":15}},
|
||||
"typeName": {
|
||||
"type": "Identifier",
|
||||
"start":14,"end":15,"loc":{"start":{"line":1,"column":14},"end":{"line":1,"column":15},"identifierName":"A"},
|
||||
"name": "A"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "TSNamedTupleMember",
|
||||
"start":17,"end":21,"loc":{"start":{"line":1,"column":17},"end":{"line":1,"column":21}},
|
||||
"optional": false,
|
||||
"label": {
|
||||
"type": "Identifier",
|
||||
"start":17,"end":18,"loc":{"start":{"line":1,"column":17},"end":{"line":1,"column":18},"identifierName":"y"},
|
||||
"name": "y"
|
||||
},
|
||||
"elementType": {
|
||||
"type": "TSTypeReference",
|
||||
"start":20,"end":21,"loc":{"start":{"line":1,"column":20},"end":{"line":1,"column":21}},
|
||||
"typeName": {
|
||||
"type": "Identifier",
|
||||
"start":20,"end":21,"loc":{"start":{"line":1,"column":20},"end":{"line":1,"column":21},"identifierName":"B"},
|
||||
"name": "B"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"directives": []
|
||||
}
|
||||
}
|
||||
@ -0,0 +1 @@
|
||||
type T = [x: A, ...B];
|
||||
@ -0,0 +1,63 @@
|
||||
{
|
||||
"type": "File",
|
||||
"start":0,"end":22,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":22}},
|
||||
"errors": [
|
||||
"SyntaxError: Tuple members must all have names or all not have names. (1:19)"
|
||||
],
|
||||
"program": {
|
||||
"type": "Program",
|
||||
"start":0,"end":22,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":22}},
|
||||
"sourceType": "module",
|
||||
"interpreter": null,
|
||||
"body": [
|
||||
{
|
||||
"type": "TSTypeAliasDeclaration",
|
||||
"start":0,"end":22,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":22}},
|
||||
"id": {
|
||||
"type": "Identifier",
|
||||
"start":5,"end":6,"loc":{"start":{"line":1,"column":5},"end":{"line":1,"column":6},"identifierName":"T"},
|
||||
"name": "T"
|
||||
},
|
||||
"typeAnnotation": {
|
||||
"type": "TSTupleType",
|
||||
"start":9,"end":21,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":21}},
|
||||
"elementTypes": [
|
||||
{
|
||||
"type": "TSNamedTupleMember",
|
||||
"start":10,"end":14,"loc":{"start":{"line":1,"column":10},"end":{"line":1,"column":14}},
|
||||
"optional": false,
|
||||
"label": {
|
||||
"type": "Identifier",
|
||||
"start":10,"end":11,"loc":{"start":{"line":1,"column":10},"end":{"line":1,"column":11},"identifierName":"x"},
|
||||
"name": "x"
|
||||
},
|
||||
"elementType": {
|
||||
"type": "TSTypeReference",
|
||||
"start":13,"end":14,"loc":{"start":{"line":1,"column":13},"end":{"line":1,"column":14}},
|
||||
"typeName": {
|
||||
"type": "Identifier",
|
||||
"start":13,"end":14,"loc":{"start":{"line":1,"column":13},"end":{"line":1,"column":14},"identifierName":"A"},
|
||||
"name": "A"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "TSRestType",
|
||||
"start":16,"end":20,"loc":{"start":{"line":1,"column":16},"end":{"line":1,"column":20}},
|
||||
"typeAnnotation": {
|
||||
"type": "TSTypeReference",
|
||||
"start":19,"end":20,"loc":{"start":{"line":1,"column":19},"end":{"line":1,"column":20}},
|
||||
"typeName": {
|
||||
"type": "Identifier",
|
||||
"start":19,"end":20,"loc":{"start":{"line":1,"column":19},"end":{"line":1,"column":20},"identifierName":"B"},
|
||||
"name": "B"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"directives": []
|
||||
}
|
||||
}
|
||||
@ -0,0 +1 @@
|
||||
type T = [...B, x: A];
|
||||
@ -0,0 +1,63 @@
|
||||
{
|
||||
"type": "File",
|
||||
"start":0,"end":22,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":22}},
|
||||
"errors": [
|
||||
"SyntaxError: Tuple members must all have names or all not have names. (1:16)"
|
||||
],
|
||||
"program": {
|
||||
"type": "Program",
|
||||
"start":0,"end":22,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":22}},
|
||||
"sourceType": "module",
|
||||
"interpreter": null,
|
||||
"body": [
|
||||
{
|
||||
"type": "TSTypeAliasDeclaration",
|
||||
"start":0,"end":22,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":22}},
|
||||
"id": {
|
||||
"type": "Identifier",
|
||||
"start":5,"end":6,"loc":{"start":{"line":1,"column":5},"end":{"line":1,"column":6},"identifierName":"T"},
|
||||
"name": "T"
|
||||
},
|
||||
"typeAnnotation": {
|
||||
"type": "TSTupleType",
|
||||
"start":9,"end":21,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":21}},
|
||||
"elementTypes": [
|
||||
{
|
||||
"type": "TSRestType",
|
||||
"start":10,"end":14,"loc":{"start":{"line":1,"column":10},"end":{"line":1,"column":14}},
|
||||
"typeAnnotation": {
|
||||
"type": "TSTypeReference",
|
||||
"start":13,"end":14,"loc":{"start":{"line":1,"column":13},"end":{"line":1,"column":14}},
|
||||
"typeName": {
|
||||
"type": "Identifier",
|
||||
"start":13,"end":14,"loc":{"start":{"line":1,"column":13},"end":{"line":1,"column":14},"identifierName":"B"},
|
||||
"name": "B"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "TSNamedTupleMember",
|
||||
"start":16,"end":20,"loc":{"start":{"line":1,"column":16},"end":{"line":1,"column":20}},
|
||||
"optional": false,
|
||||
"label": {
|
||||
"type": "Identifier",
|
||||
"start":16,"end":17,"loc":{"start":{"line":1,"column":16},"end":{"line":1,"column":17},"identifierName":"x"},
|
||||
"name": "x"
|
||||
},
|
||||
"elementType": {
|
||||
"type": "TSTypeReference",
|
||||
"start":19,"end":20,"loc":{"start":{"line":1,"column":19},"end":{"line":1,"column":20}},
|
||||
"typeName": {
|
||||
"type": "Identifier",
|
||||
"start":19,"end":20,"loc":{"start":{"line":1,"column":19},"end":{"line":1,"column":20},"identifierName":"A"},
|
||||
"name": "A"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"directives": []
|
||||
}
|
||||
}
|
||||
@ -923,6 +923,12 @@ export function assertTSOptionalType(node: Object, opts?: Object = {}): void {
|
||||
export function assertTSRestType(node: Object, opts?: Object = {}): void {
|
||||
assert("TSRestType", node, opts);
|
||||
}
|
||||
export function assertTSNamedTupleMember(
|
||||
node: Object,
|
||||
opts?: Object = {},
|
||||
): void {
|
||||
assert("TSNamedTupleMember", node, opts);
|
||||
}
|
||||
export function assertTSUnionType(node: Object, opts?: Object = {}): void {
|
||||
assert("TSUnionType", node, opts);
|
||||
}
|
||||
|
||||
@ -894,6 +894,11 @@ export function tsRestType(...args: Array<any>): Object {
|
||||
}
|
||||
export { tsRestType as TSRestType };
|
||||
export { tsRestType as tSRestType };
|
||||
export function tsNamedTupleMember(...args: Array<any>): Object {
|
||||
return builder("TSNamedTupleMember", ...args);
|
||||
}
|
||||
export { tsNamedTupleMember as TSNamedTupleMember };
|
||||
export { tsNamedTupleMember as tSNamedTupleMember };
|
||||
export function tsUnionType(...args: Array<any>): Object {
|
||||
return builder("TSUnionType", ...args);
|
||||
}
|
||||
|
||||
@ -214,7 +214,7 @@ defineType("TSTupleType", {
|
||||
aliases: ["TSType"],
|
||||
visitor: ["elementTypes"],
|
||||
fields: {
|
||||
elementTypes: validateArrayOfType("TSType"),
|
||||
elementTypes: validateArrayOfType(["TSType", "TSNamedTupleMember"]),
|
||||
},
|
||||
});
|
||||
|
||||
@ -234,6 +234,19 @@ defineType("TSRestType", {
|
||||
},
|
||||
});
|
||||
|
||||
defineType("TSNamedTupleMember", {
|
||||
visitor: ["label", "elementType"],
|
||||
builder: ["label", "elementType", "optional"],
|
||||
fields: {
|
||||
label: validateType("Identifier"),
|
||||
optional: {
|
||||
validate: bool,
|
||||
default: false,
|
||||
},
|
||||
elementType: validateType("TSType"),
|
||||
},
|
||||
});
|
||||
|
||||
const unionOrIntersection = {
|
||||
aliases: ["TSType"],
|
||||
visitor: ["types"],
|
||||
|
||||
@ -3041,6 +3041,20 @@ export function isTSRestType(node: ?Object, opts?: Object): boolean {
|
||||
|
||||
return false;
|
||||
}
|
||||
export function isTSNamedTupleMember(node: ?Object, opts?: Object): boolean {
|
||||
if (!node) return false;
|
||||
|
||||
const nodeType = node.type;
|
||||
if (nodeType === "TSNamedTupleMember") {
|
||||
if (typeof opts === "undefined") {
|
||||
return true;
|
||||
} else {
|
||||
return shallowEqual(node, opts);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
export function isTSUnionType(node: ?Object, opts?: Object): boolean {
|
||||
if (!node) return false;
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user