[ts] Add support for template interpolations in types (#12131)
Co-authored-by: Brian Ng <bng412@gmail.com>
This commit is contained in:
parent
9f40d6fcd0
commit
3fd963fdc8
2
Makefile
2
Makefile
@ -1,6 +1,6 @@
|
|||||||
FLOW_COMMIT = a1f9a4c709dcebb27a5084acf47755fbae699c25
|
FLOW_COMMIT = a1f9a4c709dcebb27a5084acf47755fbae699c25
|
||||||
TEST262_COMMIT = 058adfed86b1d4129996faaf50a85ea55379a66a
|
TEST262_COMMIT = 058adfed86b1d4129996faaf50a85ea55379a66a
|
||||||
TYPESCRIPT_COMMIT = d779a190535e52896cfe5100101173c00b6b8625
|
TYPESCRIPT_COMMIT = da8633212023517630de5f3620a23736b63234b1
|
||||||
|
|
||||||
FORCE_PUBLISH = "@babel/runtime,@babel/runtime-corejs2,@babel/runtime-corejs3,@babel/standalone"
|
FORCE_PUBLISH = "@babel/runtime,@babel/runtime-corejs2,@babel/runtime-corejs3,@babel/standalone"
|
||||||
|
|
||||||
|
|||||||
@ -1608,7 +1608,7 @@ export default class ExpressionParser extends LValParser {
|
|||||||
node.quasis = [curElt];
|
node.quasis = [curElt];
|
||||||
while (!curElt.tail) {
|
while (!curElt.tail) {
|
||||||
this.expect(tt.dollarBraceL);
|
this.expect(tt.dollarBraceL);
|
||||||
node.expressions.push(this.parseExpression());
|
node.expressions.push(this.parseTemplateSubstitution());
|
||||||
this.expect(tt.braceR);
|
this.expect(tt.braceR);
|
||||||
node.quasis.push((curElt = this.parseTemplateElement(isTagged)));
|
node.quasis.push((curElt = this.parseTemplateElement(isTagged)));
|
||||||
}
|
}
|
||||||
@ -1616,6 +1616,11 @@ export default class ExpressionParser extends LValParser {
|
|||||||
return this.finishNode(node, "TemplateLiteral");
|
return this.finishNode(node, "TemplateLiteral");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is overwritten by the TypeScript plugin to parse template types
|
||||||
|
parseTemplateSubstitution(): N.Expression {
|
||||||
|
return this.parseExpression();
|
||||||
|
}
|
||||||
|
|
||||||
// Parse an object literal, binding pattern, or record.
|
// Parse an object literal, binding pattern, or record.
|
||||||
|
|
||||||
parseObjectLike<T: N.ObjectPattern | N.ObjectExpression>(
|
parseObjectLike<T: N.ObjectPattern | N.ObjectExpression>(
|
||||||
|
|||||||
@ -94,8 +94,6 @@ const TSErrors = Object.freeze({
|
|||||||
"Private elements cannot have the 'abstract' modifier.",
|
"Private elements cannot have the 'abstract' modifier.",
|
||||||
PrivateElementHasAccessibility:
|
PrivateElementHasAccessibility:
|
||||||
"Private elements cannot have an accessibility modifier ('%0')",
|
"Private elements cannot have an accessibility modifier ('%0')",
|
||||||
TemplateTypeHasSubstitution:
|
|
||||||
"Template literal types cannot have any substitution",
|
|
||||||
TypeAnnotationAfterAssign:
|
TypeAnnotationAfterAssign:
|
||||||
"Type annotations must come before default assignments, e.g. instead of `age = 25: number` use `age: number = 25`",
|
"Type annotations must come before default assignments, e.g. instead of `age = 25: number` use `age: number = 25`",
|
||||||
UnexpectedParameterModifier:
|
UnexpectedParameterModifier:
|
||||||
@ -774,17 +772,15 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
|||||||
|
|
||||||
tsParseTemplateLiteralType(): N.TsType {
|
tsParseTemplateLiteralType(): N.TsType {
|
||||||
const node: N.TsLiteralType = this.startNode();
|
const node: N.TsLiteralType = this.startNode();
|
||||||
const templateNode = this.parseTemplate(false);
|
node.literal = this.parseTemplate(false);
|
||||||
if (templateNode.expressions.length > 0) {
|
|
||||||
this.raise(
|
|
||||||
templateNode.expressions[0].start,
|
|
||||||
TSErrors.TemplateTypeHasSubstitution,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
node.literal = templateNode;
|
|
||||||
return this.finishNode(node, "TSLiteralType");
|
return this.finishNode(node, "TSLiteralType");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
parseTemplateSubstitution(): N.TsType {
|
||||||
|
if (this.state.inType) return this.tsParseType();
|
||||||
|
return super.parseTemplateSubstitution();
|
||||||
|
}
|
||||||
|
|
||||||
tsParseThisTypeOrThisTypePredicate(): N.TsThisType | N.TsTypePredicate {
|
tsParseThisTypeOrThisTypePredicate(): N.TsThisType | N.TsTypePredicate {
|
||||||
const thisKeyword = this.tsParseThisTypeNode();
|
const thisKeyword = this.tsParseThisTypeNode();
|
||||||
if (this.isContextual("is") && !this.hasPrecedingLineBreak()) {
|
if (this.isContextual("is") && !this.hasPrecedingLineBreak()) {
|
||||||
|
|||||||
@ -1,9 +1,6 @@
|
|||||||
{
|
{
|
||||||
"type": "File",
|
"type": "File",
|
||||||
"start":0,"end":20,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":20}},
|
"start":0,"end":20,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":20}},
|
||||||
"errors": [
|
|
||||||
"SyntaxError: Template literal types cannot have any substitution (1:14)"
|
|
||||||
],
|
|
||||||
"program": {
|
"program": {
|
||||||
"type": "Program",
|
"type": "Program",
|
||||||
"start":0,"end":20,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":20}},
|
"start":0,"end":20,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":20}},
|
||||||
@ -32,9 +29,13 @@
|
|||||||
"start":7,"end":19,"loc":{"start":{"line":1,"column":7},"end":{"line":1,"column":19}},
|
"start":7,"end":19,"loc":{"start":{"line":1,"column":7},"end":{"line":1,"column":19}},
|
||||||
"expressions": [
|
"expressions": [
|
||||||
{
|
{
|
||||||
"type": "Identifier",
|
"type": "TSTypeReference",
|
||||||
"start":14,"end":17,"loc":{"start":{"line":1,"column":14},"end":{"line":1,"column":17},"identifierName":"bar"},
|
"start":14,"end":17,"loc":{"start":{"line":1,"column":14},"end":{"line":1,"column":17}},
|
||||||
"name": "bar"
|
"typeName": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start":14,"end":17,"loc":{"start":{"line":1,"column":14},"end":{"line":1,"column":17},"identifierName":"bar"},
|
||||||
|
"name": "bar"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"quasis": [
|
"quasis": [
|
||||||
|
|||||||
1
packages/babel-parser/test/fixtures/typescript/types/literal-string-3/input.ts
vendored
Normal file
1
packages/babel-parser/test/fixtures/typescript/types/literal-string-3/input.ts
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
let x: `foo-${bar + baz}`;
|
||||||
3
packages/babel-parser/test/fixtures/typescript/types/literal-string-3/options.json
vendored
Normal file
3
packages/babel-parser/test/fixtures/typescript/types/literal-string-3/options.json
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"throws": "Unexpected token, expected \"}\" (1:18)"
|
||||||
|
}
|
||||||
1
packages/babel-parser/test/fixtures/typescript/types/literal-string-4/input.ts
vendored
Normal file
1
packages/babel-parser/test/fixtures/typescript/types/literal-string-4/input.ts
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
let x: `foo-${infer bar}`;
|
||||||
73
packages/babel-parser/test/fixtures/typescript/types/literal-string-4/output.json
vendored
Normal file
73
packages/babel-parser/test/fixtures/typescript/types/literal-string-4/output.json
vendored
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
{
|
||||||
|
"type": "File",
|
||||||
|
"start":0,"end":26,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":26}},
|
||||||
|
"program": {
|
||||||
|
"type": "Program",
|
||||||
|
"start":0,"end":26,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":26}},
|
||||||
|
"sourceType": "module",
|
||||||
|
"interpreter": null,
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "VariableDeclaration",
|
||||||
|
"start":0,"end":26,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":26}},
|
||||||
|
"declarations": [
|
||||||
|
{
|
||||||
|
"type": "VariableDeclarator",
|
||||||
|
"start":4,"end":25,"loc":{"start":{"line":1,"column":4},"end":{"line":1,"column":25}},
|
||||||
|
"id": {
|
||||||
|
"type": "Identifier",
|
||||||
|
"start":4,"end":25,"loc":{"start":{"line":1,"column":4},"end":{"line":1,"column":25},"identifierName":"x"},
|
||||||
|
"name": "x",
|
||||||
|
"typeAnnotation": {
|
||||||
|
"type": "TSTypeAnnotation",
|
||||||
|
"start":5,"end":25,"loc":{"start":{"line":1,"column":5},"end":{"line":1,"column":25}},
|
||||||
|
"typeAnnotation": {
|
||||||
|
"type": "TSLiteralType",
|
||||||
|
"start":7,"end":25,"loc":{"start":{"line":1,"column":7},"end":{"line":1,"column":25}},
|
||||||
|
"literal": {
|
||||||
|
"type": "TemplateLiteral",
|
||||||
|
"start":7,"end":25,"loc":{"start":{"line":1,"column":7},"end":{"line":1,"column":25}},
|
||||||
|
"expressions": [
|
||||||
|
{
|
||||||
|
"type": "TSInferType",
|
||||||
|
"start":14,"end":23,"loc":{"start":{"line":1,"column":14},"end":{"line":1,"column":23}},
|
||||||
|
"typeParameter": {
|
||||||
|
"type": "TSTypeParameter",
|
||||||
|
"start":20,"end":23,"loc":{"start":{"line":1,"column":20},"end":{"line":1,"column":23}},
|
||||||
|
"name": "bar"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"quasis": [
|
||||||
|
{
|
||||||
|
"type": "TemplateElement",
|
||||||
|
"start":8,"end":12,"loc":{"start":{"line":1,"column":8},"end":{"line":1,"column":12}},
|
||||||
|
"value": {
|
||||||
|
"raw": "foo-",
|
||||||
|
"cooked": "foo-"
|
||||||
|
},
|
||||||
|
"tail": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TemplateElement",
|
||||||
|
"start":24,"end":24,"loc":{"start":{"line":1,"column":24},"end":{"line":1,"column":24}},
|
||||||
|
"value": {
|
||||||
|
"raw": "",
|
||||||
|
"cooked": ""
|
||||||
|
},
|
||||||
|
"tail": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"init": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"kind": "let"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"directives": []
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1841,7 +1841,13 @@ defineType("TemplateLiteral", {
|
|||||||
expressions: {
|
expressions: {
|
||||||
validate: chain(
|
validate: chain(
|
||||||
assertValueType("array"),
|
assertValueType("array"),
|
||||||
assertEach(assertNodeType("Expression")),
|
assertEach(
|
||||||
|
assertNodeType(
|
||||||
|
"Expression",
|
||||||
|
// For TypeScript template literal types
|
||||||
|
"TSType",
|
||||||
|
),
|
||||||
|
),
|
||||||
function (node, key, val) {
|
function (node, key, val) {
|
||||||
if (node.quasis.length !== val.length + 1) {
|
if (node.quasis.length !== val.length + 1) {
|
||||||
throw new TypeError(
|
throw new TypeError(
|
||||||
|
|||||||
@ -226,6 +226,7 @@ gettersAndSettersErrors.ts
|
|||||||
giant.ts
|
giant.ts
|
||||||
globalThisDeclarationEmit.ts
|
globalThisDeclarationEmit.ts
|
||||||
globalThisDeclarationEmit2.ts
|
globalThisDeclarationEmit2.ts
|
||||||
|
hugeDeclarationOutputGetsTruncatedWithError.ts
|
||||||
implementClausePrecedingExtends.ts
|
implementClausePrecedingExtends.ts
|
||||||
implementsClauseAlreadySeen.ts
|
implementsClauseAlreadySeen.ts
|
||||||
importAndVariableDeclarationConflict1.ts
|
importAndVariableDeclarationConflict1.ts
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user