mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-06 02:33:53 -06:00
Transform JSX spread children (#45693)
* Transform JSX spread children * Target es2015 to skip helper and refine emit Co-authored-by: Ron Buckton <ron.buckton@microsoft.com> Co-authored-by: Ron Buckton <ron.buckton@microsoft.com> Co-authored-by: Orta <git@orta.io>
This commit is contained in:
parent
af689cc5d5
commit
27bbdf1fe9
@ -547,7 +547,8 @@ namespace ts {
|
||||
}
|
||||
|
||||
function visitJsxExpression(node: JsxExpression) {
|
||||
return visitNode(node.expression, visitor, isExpression);
|
||||
const expression = visitNode(node.expression, visitor, isExpression);
|
||||
return node.dotDotDotToken ? factory.createSpreadElement(expression!) : expression;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -89,31 +89,36 @@ const _brokenTree2 = <DOMSFC x={1} y={2}>{tree}{tree}</DOMSFC>
|
||||
|
||||
//// [component.js]
|
||||
"use strict";
|
||||
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
||||
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
||||
if (ar || !(i in from)) {
|
||||
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
||||
ar[i] = from[i];
|
||||
}
|
||||
}
|
||||
return to.concat(ar || Array.prototype.slice.call(from));
|
||||
};
|
||||
var _this = this;
|
||||
exports.__esModule = true;
|
||||
exports.tree = exports.MyClass = exports.MySFC = void 0;
|
||||
/** @jsx predom */
|
||||
var renderer2_1 = require("./renderer2");
|
||||
var MySFC = function (props) { return (0, renderer2_1.predom)("p", null,
|
||||
props.x,
|
||||
var MySFC = function (props) { return renderer2_1.predom.apply(void 0, __spreadArray(["p", null, props.x,
|
||||
" + ",
|
||||
props.y,
|
||||
" = ",
|
||||
props.x + props.y,
|
||||
_this.props.children); };
|
||||
props.x + props.y], _this.props.children, false)); };
|
||||
exports.MySFC = MySFC;
|
||||
var MyClass = /** @class */ (function () {
|
||||
function MyClass(props) {
|
||||
this.props = props;
|
||||
}
|
||||
MyClass.prototype.render = function () {
|
||||
return (0, renderer2_1.predom)("p", null,
|
||||
this.props.x,
|
||||
return renderer2_1.predom.apply(void 0, __spreadArray(["p", null, this.props.x,
|
||||
" + ",
|
||||
this.props.y,
|
||||
" = ",
|
||||
this.props.x + this.props.y,
|
||||
this.props.children);
|
||||
this.props.x + this.props.y], this.props.children, false));
|
||||
};
|
||||
return MyClass;
|
||||
}());
|
||||
@ -124,6 +129,15 @@ exports.tree = (0, renderer2_1.predom)(exports.MySFC, { x: 1, y: 2 },
|
||||
exports["default"] = (0, renderer2_1.predom)("h", null);
|
||||
//// [index.js]
|
||||
"use strict";
|
||||
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
||||
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
||||
if (ar || !(i in from)) {
|
||||
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
||||
ar[i] = from[i];
|
||||
}
|
||||
}
|
||||
return to.concat(ar || Array.prototype.slice.call(from));
|
||||
};
|
||||
exports.__esModule = true;
|
||||
/** @jsx dom */
|
||||
var renderer_1 = require("./renderer");
|
||||
@ -142,13 +156,11 @@ var DOMClass = /** @class */ (function () {
|
||||
this.props = props;
|
||||
}
|
||||
DOMClass.prototype.render = function () {
|
||||
return (0, renderer_1.dom)("p", null,
|
||||
this.props.x,
|
||||
return renderer_1.dom.apply(void 0, __spreadArray(["p", null, this.props.x,
|
||||
" + ",
|
||||
this.props.y,
|
||||
" = ",
|
||||
this.props.x + this.props.y,
|
||||
this.props.children);
|
||||
this.props.x + this.props.y], this.props.children, false));
|
||||
};
|
||||
return DOMClass;
|
||||
}());
|
||||
|
||||
@ -0,0 +1,47 @@
|
||||
//// [tsxSpreadChildrenInvalidType.tsx]
|
||||
declare module JSX {
|
||||
interface Element { }
|
||||
interface IntrinsicElements {
|
||||
[s: string]: any;
|
||||
}
|
||||
}
|
||||
declare var React: any;
|
||||
|
||||
interface TodoProp {
|
||||
id: number;
|
||||
todo: string;
|
||||
}
|
||||
interface TodoListProps {
|
||||
todos: TodoProp[];
|
||||
}
|
||||
function Todo(prop: { key: number, todo: string }) {
|
||||
return <div>{prop.key.toString() + prop.todo}</div>;
|
||||
}
|
||||
function TodoList({ todos }: TodoListProps) {
|
||||
return <div>
|
||||
{...<Todo key={todos[0].id} todo={todos[0].todo} />}
|
||||
</div>;
|
||||
}
|
||||
function TodoListNoError({ todos }: TodoListProps) {
|
||||
// any is not checked
|
||||
return <div>
|
||||
{...(<Todo key={todos[0].id} todo={todos[0].todo} /> as any)}
|
||||
</div>;
|
||||
}
|
||||
let x: TodoListProps;
|
||||
<TodoList {...x}/>
|
||||
|
||||
|
||||
//// [tsxSpreadChildrenInvalidType.js]
|
||||
function Todo(prop) {
|
||||
return React.createElement("div", null, prop.key.toString() + prop.todo);
|
||||
}
|
||||
function TodoList({ todos }) {
|
||||
return React.createElement("div", null, ...React.createElement(Todo, { key: todos[0].id, todo: todos[0].todo }));
|
||||
}
|
||||
function TodoListNoError({ todos }) {
|
||||
// any is not checked
|
||||
return React.createElement("div", null, ...React.createElement(Todo, { key: todos[0].id, todo: todos[0].todo }));
|
||||
}
|
||||
let x;
|
||||
React.createElement(TodoList, Object.assign({}, x));
|
||||
@ -0,0 +1,38 @@
|
||||
tests/cases/conformance/jsx/tsxSpreadChildrenInvalidType.tsx(21,9): error TS2609: JSX spread child must be an array type.
|
||||
|
||||
|
||||
==== tests/cases/conformance/jsx/tsxSpreadChildrenInvalidType.tsx (1 errors) ====
|
||||
declare module JSX {
|
||||
interface Element { }
|
||||
interface IntrinsicElements {
|
||||
[s: string]: any;
|
||||
}
|
||||
}
|
||||
declare var React: any;
|
||||
|
||||
interface TodoProp {
|
||||
id: number;
|
||||
todo: string;
|
||||
}
|
||||
interface TodoListProps {
|
||||
todos: TodoProp[];
|
||||
}
|
||||
function Todo(prop: { key: number, todo: string }) {
|
||||
return <div>{prop.key.toString() + prop.todo}</div>;
|
||||
}
|
||||
function TodoList({ todos }: TodoListProps) {
|
||||
return <div>
|
||||
{...<Todo key={todos[0].id} todo={todos[0].todo} />}
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
!!! error TS2609: JSX spread child must be an array type.
|
||||
</div>;
|
||||
}
|
||||
function TodoListNoError({ todos }: TodoListProps) {
|
||||
// any is not checked
|
||||
return <div>
|
||||
{...(<Todo key={todos[0].id} todo={todos[0].todo} /> as any)}
|
||||
</div>;
|
||||
}
|
||||
let x: TodoListProps;
|
||||
<TodoList {...x}/>
|
||||
|
||||
@ -44,17 +44,26 @@ var __assign = (this && this.__assign) || function () {
|
||||
};
|
||||
return __assign.apply(this, arguments);
|
||||
};
|
||||
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
||||
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
||||
if (ar || !(i in from)) {
|
||||
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
||||
ar[i] = from[i];
|
||||
}
|
||||
}
|
||||
return to.concat(ar || Array.prototype.slice.call(from));
|
||||
};
|
||||
function Todo(prop) {
|
||||
return React.createElement("div", null, prop.key.toString() + prop.todo);
|
||||
}
|
||||
function TodoList(_a) {
|
||||
var todos = _a.todos;
|
||||
return React.createElement("div", null, React.createElement(Todo, { key: todos[0].id, todo: todos[0].todo }));
|
||||
return React.createElement.apply(React, __spreadArray(["div", null], React.createElement(Todo, { key: todos[0].id, todo: todos[0].todo }), false));
|
||||
}
|
||||
function TodoListNoError(_a) {
|
||||
var todos = _a.todos;
|
||||
// any is not checked
|
||||
return React.createElement("div", null, React.createElement(Todo, { key: todos[0].id, todo: todos[0].todo }));
|
||||
return React.createElement.apply(React, __spreadArray(["div", null], React.createElement(Todo, { key: todos[0].id, todo: todos[0].todo }), false));
|
||||
}
|
||||
var x;
|
||||
React.createElement(TodoList, __assign({}, x));
|
||||
@ -0,0 +1,104 @@
|
||||
=== tests/cases/conformance/jsx/tsxSpreadChildrenInvalidType.tsx ===
|
||||
declare module JSX {
|
||||
>JSX : Symbol(JSX, Decl(tsxSpreadChildrenInvalidType.tsx, 0, 0))
|
||||
|
||||
interface Element { }
|
||||
>Element : Symbol(Element, Decl(tsxSpreadChildrenInvalidType.tsx, 0, 20))
|
||||
|
||||
interface IntrinsicElements {
|
||||
>IntrinsicElements : Symbol(IntrinsicElements, Decl(tsxSpreadChildrenInvalidType.tsx, 1, 22))
|
||||
|
||||
[s: string]: any;
|
||||
>s : Symbol(s, Decl(tsxSpreadChildrenInvalidType.tsx, 3, 3))
|
||||
}
|
||||
}
|
||||
declare var React: any;
|
||||
>React : Symbol(React, Decl(tsxSpreadChildrenInvalidType.tsx, 6, 11))
|
||||
|
||||
interface TodoProp {
|
||||
>TodoProp : Symbol(TodoProp, Decl(tsxSpreadChildrenInvalidType.tsx, 6, 23))
|
||||
|
||||
id: number;
|
||||
>id : Symbol(TodoProp.id, Decl(tsxSpreadChildrenInvalidType.tsx, 8, 20))
|
||||
|
||||
todo: string;
|
||||
>todo : Symbol(TodoProp.todo, Decl(tsxSpreadChildrenInvalidType.tsx, 9, 15))
|
||||
}
|
||||
interface TodoListProps {
|
||||
>TodoListProps : Symbol(TodoListProps, Decl(tsxSpreadChildrenInvalidType.tsx, 11, 1))
|
||||
|
||||
todos: TodoProp[];
|
||||
>todos : Symbol(TodoListProps.todos, Decl(tsxSpreadChildrenInvalidType.tsx, 12, 25))
|
||||
>TodoProp : Symbol(TodoProp, Decl(tsxSpreadChildrenInvalidType.tsx, 6, 23))
|
||||
}
|
||||
function Todo(prop: { key: number, todo: string }) {
|
||||
>Todo : Symbol(Todo, Decl(tsxSpreadChildrenInvalidType.tsx, 14, 1))
|
||||
>prop : Symbol(prop, Decl(tsxSpreadChildrenInvalidType.tsx, 15, 14))
|
||||
>key : Symbol(key, Decl(tsxSpreadChildrenInvalidType.tsx, 15, 21))
|
||||
>todo : Symbol(todo, Decl(tsxSpreadChildrenInvalidType.tsx, 15, 34))
|
||||
|
||||
return <div>{prop.key.toString() + prop.todo}</div>;
|
||||
>div : Symbol(JSX.IntrinsicElements, Decl(tsxSpreadChildrenInvalidType.tsx, 1, 22))
|
||||
>prop.key.toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --))
|
||||
>prop.key : Symbol(key, Decl(tsxSpreadChildrenInvalidType.tsx, 15, 21))
|
||||
>prop : Symbol(prop, Decl(tsxSpreadChildrenInvalidType.tsx, 15, 14))
|
||||
>key : Symbol(key, Decl(tsxSpreadChildrenInvalidType.tsx, 15, 21))
|
||||
>toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --))
|
||||
>prop.todo : Symbol(todo, Decl(tsxSpreadChildrenInvalidType.tsx, 15, 34))
|
||||
>prop : Symbol(prop, Decl(tsxSpreadChildrenInvalidType.tsx, 15, 14))
|
||||
>todo : Symbol(todo, Decl(tsxSpreadChildrenInvalidType.tsx, 15, 34))
|
||||
>div : Symbol(JSX.IntrinsicElements, Decl(tsxSpreadChildrenInvalidType.tsx, 1, 22))
|
||||
}
|
||||
function TodoList({ todos }: TodoListProps) {
|
||||
>TodoList : Symbol(TodoList, Decl(tsxSpreadChildrenInvalidType.tsx, 17, 1))
|
||||
>todos : Symbol(todos, Decl(tsxSpreadChildrenInvalidType.tsx, 18, 19))
|
||||
>TodoListProps : Symbol(TodoListProps, Decl(tsxSpreadChildrenInvalidType.tsx, 11, 1))
|
||||
|
||||
return <div>
|
||||
>div : Symbol(JSX.IntrinsicElements, Decl(tsxSpreadChildrenInvalidType.tsx, 1, 22))
|
||||
|
||||
{...<Todo key={todos[0].id} todo={todos[0].todo} />}
|
||||
>Todo : Symbol(Todo, Decl(tsxSpreadChildrenInvalidType.tsx, 14, 1))
|
||||
>key : Symbol(key, Decl(tsxSpreadChildrenInvalidType.tsx, 20, 17))
|
||||
>todos[0].id : Symbol(TodoProp.id, Decl(tsxSpreadChildrenInvalidType.tsx, 8, 20))
|
||||
>todos : Symbol(todos, Decl(tsxSpreadChildrenInvalidType.tsx, 18, 19))
|
||||
>id : Symbol(TodoProp.id, Decl(tsxSpreadChildrenInvalidType.tsx, 8, 20))
|
||||
>todo : Symbol(todo, Decl(tsxSpreadChildrenInvalidType.tsx, 20, 35))
|
||||
>todos[0].todo : Symbol(TodoProp.todo, Decl(tsxSpreadChildrenInvalidType.tsx, 9, 15))
|
||||
>todos : Symbol(todos, Decl(tsxSpreadChildrenInvalidType.tsx, 18, 19))
|
||||
>todo : Symbol(TodoProp.todo, Decl(tsxSpreadChildrenInvalidType.tsx, 9, 15))
|
||||
|
||||
</div>;
|
||||
>div : Symbol(JSX.IntrinsicElements, Decl(tsxSpreadChildrenInvalidType.tsx, 1, 22))
|
||||
}
|
||||
function TodoListNoError({ todos }: TodoListProps) {
|
||||
>TodoListNoError : Symbol(TodoListNoError, Decl(tsxSpreadChildrenInvalidType.tsx, 22, 1))
|
||||
>todos : Symbol(todos, Decl(tsxSpreadChildrenInvalidType.tsx, 23, 26))
|
||||
>TodoListProps : Symbol(TodoListProps, Decl(tsxSpreadChildrenInvalidType.tsx, 11, 1))
|
||||
|
||||
// any is not checked
|
||||
return <div>
|
||||
>div : Symbol(JSX.IntrinsicElements, Decl(tsxSpreadChildrenInvalidType.tsx, 1, 22))
|
||||
|
||||
{...(<Todo key={todos[0].id} todo={todos[0].todo} /> as any)}
|
||||
>Todo : Symbol(Todo, Decl(tsxSpreadChildrenInvalidType.tsx, 14, 1))
|
||||
>key : Symbol(key, Decl(tsxSpreadChildrenInvalidType.tsx, 26, 18))
|
||||
>todos[0].id : Symbol(TodoProp.id, Decl(tsxSpreadChildrenInvalidType.tsx, 8, 20))
|
||||
>todos : Symbol(todos, Decl(tsxSpreadChildrenInvalidType.tsx, 23, 26))
|
||||
>id : Symbol(TodoProp.id, Decl(tsxSpreadChildrenInvalidType.tsx, 8, 20))
|
||||
>todo : Symbol(todo, Decl(tsxSpreadChildrenInvalidType.tsx, 26, 36))
|
||||
>todos[0].todo : Symbol(TodoProp.todo, Decl(tsxSpreadChildrenInvalidType.tsx, 9, 15))
|
||||
>todos : Symbol(todos, Decl(tsxSpreadChildrenInvalidType.tsx, 23, 26))
|
||||
>todo : Symbol(TodoProp.todo, Decl(tsxSpreadChildrenInvalidType.tsx, 9, 15))
|
||||
|
||||
</div>;
|
||||
>div : Symbol(JSX.IntrinsicElements, Decl(tsxSpreadChildrenInvalidType.tsx, 1, 22))
|
||||
}
|
||||
let x: TodoListProps;
|
||||
>x : Symbol(x, Decl(tsxSpreadChildrenInvalidType.tsx, 29, 3))
|
||||
>TodoListProps : Symbol(TodoListProps, Decl(tsxSpreadChildrenInvalidType.tsx, 11, 1))
|
||||
|
||||
<TodoList {...x}/>
|
||||
>TodoList : Symbol(TodoList, Decl(tsxSpreadChildrenInvalidType.tsx, 17, 1))
|
||||
>x : Symbol(x, Decl(tsxSpreadChildrenInvalidType.tsx, 29, 3))
|
||||
|
||||
@ -0,0 +1,108 @@
|
||||
=== tests/cases/conformance/jsx/tsxSpreadChildrenInvalidType.tsx ===
|
||||
declare module JSX {
|
||||
interface Element { }
|
||||
interface IntrinsicElements {
|
||||
[s: string]: any;
|
||||
>s : string
|
||||
}
|
||||
}
|
||||
declare var React: any;
|
||||
>React : any
|
||||
|
||||
interface TodoProp {
|
||||
id: number;
|
||||
>id : number
|
||||
|
||||
todo: string;
|
||||
>todo : string
|
||||
}
|
||||
interface TodoListProps {
|
||||
todos: TodoProp[];
|
||||
>todos : TodoProp[]
|
||||
}
|
||||
function Todo(prop: { key: number, todo: string }) {
|
||||
>Todo : (prop: { key: number; todo: string;}) => JSX.Element
|
||||
>prop : { key: number; todo: string; }
|
||||
>key : number
|
||||
>todo : string
|
||||
|
||||
return <div>{prop.key.toString() + prop.todo}</div>;
|
||||
><div>{prop.key.toString() + prop.todo}</div> : JSX.Element
|
||||
>div : any
|
||||
>prop.key.toString() + prop.todo : string
|
||||
>prop.key.toString() : string
|
||||
>prop.key.toString : (radix?: number) => string
|
||||
>prop.key : number
|
||||
>prop : { key: number; todo: string; }
|
||||
>key : number
|
||||
>toString : (radix?: number) => string
|
||||
>prop.todo : string
|
||||
>prop : { key: number; todo: string; }
|
||||
>todo : string
|
||||
>div : any
|
||||
}
|
||||
function TodoList({ todos }: TodoListProps) {
|
||||
>TodoList : ({ todos }: TodoListProps) => JSX.Element
|
||||
>todos : TodoProp[]
|
||||
|
||||
return <div>
|
||||
><div> {...<Todo key={todos[0].id} todo={todos[0].todo} />} </div> : JSX.Element
|
||||
>div : any
|
||||
|
||||
{...<Todo key={todos[0].id} todo={todos[0].todo} />}
|
||||
><Todo key={todos[0].id} todo={todos[0].todo} /> : JSX.Element
|
||||
>Todo : (prop: { key: number; todo: string; }) => JSX.Element
|
||||
>key : number
|
||||
>todos[0].id : number
|
||||
>todos[0] : TodoProp
|
||||
>todos : TodoProp[]
|
||||
>0 : 0
|
||||
>id : number
|
||||
>todo : string
|
||||
>todos[0].todo : string
|
||||
>todos[0] : TodoProp
|
||||
>todos : TodoProp[]
|
||||
>0 : 0
|
||||
>todo : string
|
||||
|
||||
</div>;
|
||||
>div : any
|
||||
}
|
||||
function TodoListNoError({ todos }: TodoListProps) {
|
||||
>TodoListNoError : ({ todos }: TodoListProps) => JSX.Element
|
||||
>todos : TodoProp[]
|
||||
|
||||
// any is not checked
|
||||
return <div>
|
||||
><div> {...(<Todo key={todos[0].id} todo={todos[0].todo} /> as any)} </div> : JSX.Element
|
||||
>div : any
|
||||
|
||||
{...(<Todo key={todos[0].id} todo={todos[0].todo} /> as any)}
|
||||
>(<Todo key={todos[0].id} todo={todos[0].todo} /> as any) : any
|
||||
><Todo key={todos[0].id} todo={todos[0].todo} /> as any : any
|
||||
><Todo key={todos[0].id} todo={todos[0].todo} /> : JSX.Element
|
||||
>Todo : (prop: { key: number; todo: string; }) => JSX.Element
|
||||
>key : number
|
||||
>todos[0].id : number
|
||||
>todos[0] : TodoProp
|
||||
>todos : TodoProp[]
|
||||
>0 : 0
|
||||
>id : number
|
||||
>todo : string
|
||||
>todos[0].todo : string
|
||||
>todos[0] : TodoProp
|
||||
>todos : TodoProp[]
|
||||
>0 : 0
|
||||
>todo : string
|
||||
|
||||
</div>;
|
||||
>div : any
|
||||
}
|
||||
let x: TodoListProps;
|
||||
>x : TodoListProps
|
||||
|
||||
<TodoList {...x}/>
|
||||
><TodoList {...x}/> : JSX.Element
|
||||
>TodoList : ({ todos }: TodoListProps) => JSX.Element
|
||||
>x : TodoListProps
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
// @jsx: react
|
||||
// @target: es2015,es5
|
||||
declare module JSX {
|
||||
interface Element { }
|
||||
interface IntrinsicElements {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user