[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
|
||||
TEST262_COMMIT = 058adfed86b1d4129996faaf50a85ea55379a66a
|
||||
TYPESCRIPT_COMMIT = d779a190535e52896cfe5100101173c00b6b8625
|
||||
TYPESCRIPT_COMMIT = da8633212023517630de5f3620a23736b63234b1
|
||||
|
||||
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];
|
||||
while (!curElt.tail) {
|
||||
this.expect(tt.dollarBraceL);
|
||||
node.expressions.push(this.parseExpression());
|
||||
node.expressions.push(this.parseTemplateSubstitution());
|
||||
this.expect(tt.braceR);
|
||||
node.quasis.push((curElt = this.parseTemplateElement(isTagged)));
|
||||
}
|
||||
@ -1616,6 +1616,11 @@ export default class ExpressionParser extends LValParser {
|
||||
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.
|
||||
|
||||
parseObjectLike<T: N.ObjectPattern | N.ObjectExpression>(
|
||||
|
||||
@ -94,8 +94,6 @@ const TSErrors = Object.freeze({
|
||||
"Private elements cannot have the 'abstract' modifier.",
|
||||
PrivateElementHasAccessibility:
|
||||
"Private elements cannot have an accessibility modifier ('%0')",
|
||||
TemplateTypeHasSubstitution:
|
||||
"Template literal types cannot have any substitution",
|
||||
TypeAnnotationAfterAssign:
|
||||
"Type annotations must come before default assignments, e.g. instead of `age = 25: number` use `age: number = 25`",
|
||||
UnexpectedParameterModifier:
|
||||
@ -774,17 +772,15 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
|
||||
tsParseTemplateLiteralType(): N.TsType {
|
||||
const node: N.TsLiteralType = this.startNode();
|
||||
const templateNode = this.parseTemplate(false);
|
||||
if (templateNode.expressions.length > 0) {
|
||||
this.raise(
|
||||
templateNode.expressions[0].start,
|
||||
TSErrors.TemplateTypeHasSubstitution,
|
||||
);
|
||||
}
|
||||
node.literal = templateNode;
|
||||
node.literal = this.parseTemplate(false);
|
||||
return this.finishNode(node, "TSLiteralType");
|
||||
}
|
||||
|
||||
parseTemplateSubstitution(): N.TsType {
|
||||
if (this.state.inType) return this.tsParseType();
|
||||
return super.parseTemplateSubstitution();
|
||||
}
|
||||
|
||||
tsParseThisTypeOrThisTypePredicate(): N.TsThisType | N.TsTypePredicate {
|
||||
const thisKeyword = this.tsParseThisTypeNode();
|
||||
if (this.isContextual("is") && !this.hasPrecedingLineBreak()) {
|
||||
|
||||
@ -1,9 +1,6 @@
|
||||
{
|
||||
"type": "File",
|
||||
"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": {
|
||||
"type": "Program",
|
||||
"start":0,"end":20,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":20}},
|
||||
@ -32,10 +29,14 @@
|
||||
"start":7,"end":19,"loc":{"start":{"line":1,"column":7},"end":{"line":1,"column":19}},
|
||||
"expressions": [
|
||||
{
|
||||
"type": "TSTypeReference",
|
||||
"start":14,"end":17,"loc":{"start":{"line":1,"column":14},"end":{"line":1,"column":17}},
|
||||
"typeName": {
|
||||
"type": "Identifier",
|
||||
"start":14,"end":17,"loc":{"start":{"line":1,"column":14},"end":{"line":1,"column":17},"identifierName":"bar"},
|
||||
"name": "bar"
|
||||
}
|
||||
}
|
||||
],
|
||||
"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: {
|
||||
validate: chain(
|
||||
assertValueType("array"),
|
||||
assertEach(assertNodeType("Expression")),
|
||||
assertEach(
|
||||
assertNodeType(
|
||||
"Expression",
|
||||
// For TypeScript template literal types
|
||||
"TSType",
|
||||
),
|
||||
),
|
||||
function (node, key, val) {
|
||||
if (node.quasis.length !== val.length + 1) {
|
||||
throw new TypeError(
|
||||
|
||||
@ -226,6 +226,7 @@ gettersAndSettersErrors.ts
|
||||
giant.ts
|
||||
globalThisDeclarationEmit.ts
|
||||
globalThisDeclarationEmit2.ts
|
||||
hugeDeclarationOutputGetsTruncatedWithError.ts
|
||||
implementClausePrecedingExtends.ts
|
||||
implementsClauseAlreadySeen.ts
|
||||
importAndVariableDeclarationConflict1.ts
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user