Skip to content

Commit 0faf32b

Browse files
committed
Add spread syntax to JsxExpression.
This allows you to specify that a JsxExpression should be a list that will be flattened by the JSX consumer.
1 parent 4ccb3bb commit 0faf32b

File tree

6 files changed

+20
-5
lines changed

6 files changed

+20
-5
lines changed

src/compiler/checker.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10904,7 +10904,11 @@ namespace ts {
1090410904

1090510905
function checkJsxExpression(node: JsxExpression) {
1090610906
if (node.expression) {
10907-
return checkExpression(node.expression);
10907+
const type = checkExpression(node.expression);
10908+
if (node.dotDotDotToken && !isArrayType(type)) {
10909+
error(node, Diagnostics.JSX_spread_child_must_be_an_array_type, node.toString(), typeToString(type));
10910+
}
10911+
return type;
1090810912
}
1090910913
else {
1091010914
return unknownType;

src/compiler/diagnosticMessages.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1787,6 +1787,10 @@
17871787
"category": "Error",
17881788
"code": 2608
17891789
},
1790+
"JSX spread child must be an array type.": {
1791+
"category": "Error",
1792+
"code": 2609
1793+
},
17901794
"Cannot emit namespaced JSX elements in React": {
17911795
"category": "Error",
17921796
"code": 2650

src/compiler/emitter.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1969,6 +1969,9 @@ const _super = (function (geti, seti) {
19691969
function emitJsxExpression(node: JsxExpression) {
19701970
if (node.expression) {
19711971
write("{");
1972+
if (node.dotDotDotToken) {
1973+
write("...");
1974+
}
19721975
emitExpression(node.expression);
19731976
write("}");
19741977
}

src/compiler/factory.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1318,15 +1318,16 @@ namespace ts {
13181318
return node;
13191319
}
13201320

1321-
export function createJsxExpression(expression: Expression, location?: TextRange) {
1321+
export function createJsxExpression(expression: Expression, dotDotDotToken: Token<SyntaxKind.DotDotDotToken>, location?: TextRange) {
13221322
const node = <JsxExpression>createNode(SyntaxKind.JsxExpression, location);
1323+
node.dotDotDotToken = dotDotDotToken;
13231324
node.expression = expression;
13241325
return node;
13251326
}
13261327

13271328
export function updateJsxExpression(node: JsxExpression, expression: Expression) {
13281329
if (node.expression !== expression) {
1329-
return updateNode(createJsxExpression(expression, node), node);
1330+
return updateNode(createJsxExpression(expression, node.dotDotDotToken, node), node);
13301331
}
13311332
return node;
13321333
}
@@ -2910,4 +2911,4 @@ namespace ts {
29102911
function tryGetModuleNameFromDeclaration(declaration: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration, host: EmitHost, resolver: EmitResolver, compilerOptions: CompilerOptions) {
29112912
return tryGetModuleNameFromFile(resolver.getExternalModuleFileFromDeclaration(declaration), host, compilerOptions);
29122913
}
2913-
}
2914+
}

src/compiler/parser.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,8 @@ namespace ts {
362362
case SyntaxKind.JsxSpreadAttribute:
363363
return visitNode(cbNode, (<JsxSpreadAttribute>node).expression);
364364
case SyntaxKind.JsxExpression:
365-
return visitNode(cbNode, (<JsxExpression>node).expression);
365+
return visitNode(cbNode, (node as JsxExpression).dotDotDotToken) ||
366+
visitNode(cbNode, (node as JsxExpression).expression);
366367
case SyntaxKind.JsxClosingElement:
367368
return visitNode(cbNode, (<JsxClosingElement>node).tagName);
368369

@@ -3821,6 +3822,7 @@ namespace ts {
38213822

38223823
parseExpected(SyntaxKind.OpenBraceToken);
38233824
if (token() !== SyntaxKind.CloseBraceToken) {
3825+
node.dotDotDotToken = parseOptionalToken(SyntaxKind.DotDotDotToken);
38243826
node.expression = parseAssignmentExpressionOrHigher();
38253827
}
38263828
if (inExpressionContext) {

src/compiler/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1396,6 +1396,7 @@ namespace ts {
13961396

13971397
export interface JsxExpression extends Expression {
13981398
kind: SyntaxKind.JsxExpression;
1399+
dotDotDotToken?: Token<SyntaxKind.DotDotDotToken>;
13991400
expression?: Expression;
14001401
}
14011402

0 commit comments

Comments
 (0)