Skip to content

Commit f43af5e

Browse files
authored
Merge pull request #15548 from Microsoft/release-fix15469
[Release - React] Fix 15469
2 parents 8a30678 + b77c0ad commit f43af5e

19 files changed

+433
-21
lines changed

src/compiler/checker.ts

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -13211,6 +13211,8 @@ namespace ts {
1321113211
let attributesTable = createMap<Symbol>();
1321213212
let spread: Type = emptyObjectType;
1321313213
let attributesArray: Symbol[] = [];
13214+
let hasSpreadAnyType = false;
13215+
1321413216
for (const attributeDecl of attributes.properties) {
1321513217
const member = attributeDecl.symbol;
1321613218
if (isJsxAttribute(attributeDecl)) {
@@ -13239,31 +13241,33 @@ namespace ts {
1323913241
const exprType = checkExpression(attributeDecl.expression);
1324013242
if (!isValidSpreadType(exprType)) {
1324113243
error(attributeDecl, Diagnostics.Spread_types_may_only_be_created_from_object_types);
13242-
return anyType;
13244+
hasSpreadAnyType = true;
1324313245
}
1324413246
if (isTypeAny(exprType)) {
13245-
return anyType;
13247+
hasSpreadAnyType = true;
1324613248
}
1324713249
spread = getSpreadType(spread, exprType);
1324813250
}
1324913251
}
1325013252

13251-
if (spread !== emptyObjectType) {
13252-
if (attributesArray.length > 0) {
13253-
spread = getSpreadType(spread, createJsxAttributesType(attributes.symbol, attributesTable));
13254-
attributesArray = [];
13255-
attributesTable = createMap<Symbol>();
13253+
if (!hasSpreadAnyType) {
13254+
if (spread !== emptyObjectType) {
13255+
if (attributesArray.length > 0) {
13256+
spread = getSpreadType(spread, createJsxAttributesType(attributes.symbol, attributesTable));
13257+
attributesArray = [];
13258+
attributesTable = createMap<Symbol>();
13259+
}
13260+
attributesArray = getPropertiesOfType(spread);
1325613261
}
13257-
attributesArray = getPropertiesOfType(spread);
13258-
}
1325913262

13260-
attributesTable = createMap<Symbol>();
13261-
if (attributesArray) {
13262-
forEach(attributesArray, (attr) => {
13263-
if (!filter || filter(attr)) {
13264-
attributesTable.set(attr.name, attr);
13265-
}
13266-
});
13263+
attributesTable = createMap<Symbol>();
13264+
if (attributesArray) {
13265+
forEach(attributesArray, (attr) => {
13266+
if (!filter || filter(attr)) {
13267+
attributesTable.set(attr.name, attr);
13268+
}
13269+
});
13270+
}
1326713271
}
1326813272

1326913273
// Handle children attribute
@@ -13287,7 +13291,7 @@ namespace ts {
1328713291
// Error if there is a attribute named "children" and children element.
1328813292
// This is because children element will overwrite the value from attributes
1328913293
const jsxChildrenPropertyName = getJsxElementChildrenPropertyname();
13290-
if (jsxChildrenPropertyName && jsxChildrenPropertyName !== "") {
13294+
if (!hasSpreadAnyType && jsxChildrenPropertyName && jsxChildrenPropertyName !== "") {
1329113295
if (attributesTable.has(jsxChildrenPropertyName)) {
1329213296
error(attributes, Diagnostics._0_are_specified_twice_The_attribute_named_0_will_be_overwritten, jsxChildrenPropertyName);
1329313297
}
@@ -13301,7 +13305,7 @@ namespace ts {
1330113305
}
1330213306
}
1330313307

13304-
return createJsxAttributesType(attributes.symbol, attributesTable);
13308+
return hasSpreadAnyType ? anyType : createJsxAttributesType(attributes.symbol, attributesTable);
1330513309

1330613310
/**
1330713311
* Create anonymous type from given attributes symbol table.
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//// [tests/cases/conformance/jsx/correctlyMarkAliasAsReferences1.tsx] ////
2+
3+
//// [declaration.d.ts]
4+
declare module "classnames";
5+
6+
//// [0.tsx]
7+
///<reference path="declaration.d.ts" />
8+
import * as cx from 'classnames';
9+
import * as React from "react";
10+
11+
let buttonProps; // any
12+
let k = <button {...buttonProps}>
13+
<span className={cx('class1', { class2: true })} />
14+
</button>;
15+
16+
17+
//// [0.js]
18+
///<reference path="declaration.d.ts" />
19+
import * as cx from 'classnames';
20+
import * as React from "react";
21+
let buttonProps; // any
22+
let k = React.createElement("button", Object.assign({}, buttonProps),
23+
React.createElement("span", { className: cx('class1', { class2: true }) }));
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
=== tests/cases/conformance/jsx/0.tsx ===
2+
///<reference path="declaration.d.ts" />
3+
import * as cx from 'classnames';
4+
>cx : Symbol(cx, Decl(0.tsx, 1, 6))
5+
6+
import * as React from "react";
7+
>React : Symbol(React, Decl(0.tsx, 2, 6))
8+
9+
let buttonProps; // any
10+
>buttonProps : Symbol(buttonProps, Decl(0.tsx, 4, 3))
11+
12+
let k = <button {...buttonProps}>
13+
>k : Symbol(k, Decl(0.tsx, 5, 3))
14+
>button : Symbol(JSX.IntrinsicElements.button, Decl(react.d.ts, 2385, 43))
15+
>buttonProps : Symbol(buttonProps, Decl(0.tsx, 4, 3))
16+
17+
<span className={cx('class1', { class2: true })} />
18+
>span : Symbol(JSX.IntrinsicElements.span, Decl(react.d.ts, 2460, 51))
19+
>className : Symbol(className, Decl(0.tsx, 6, 17))
20+
>cx : Symbol(cx, Decl(0.tsx, 1, 6))
21+
>class2 : Symbol(class2, Decl(0.tsx, 6, 43))
22+
23+
</button>;
24+
>button : Symbol(JSX.IntrinsicElements.button, Decl(react.d.ts, 2385, 43))
25+
26+
=== tests/cases/conformance/jsx/declaration.d.ts ===
27+
declare module "classnames";
28+
No type information for this code.
29+
No type information for this code.
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
=== tests/cases/conformance/jsx/0.tsx ===
2+
///<reference path="declaration.d.ts" />
3+
import * as cx from 'classnames';
4+
>cx : any
5+
6+
import * as React from "react";
7+
>React : typeof React
8+
9+
let buttonProps; // any
10+
>buttonProps : any
11+
12+
let k = <button {...buttonProps}>
13+
>k : JSX.Element
14+
><button {...buttonProps}> <span className={cx('class1', { class2: true })} /> </button> : JSX.Element
15+
>button : any
16+
>buttonProps : any
17+
18+
<span className={cx('class1', { class2: true })} />
19+
><span className={cx('class1', { class2: true })} /> : JSX.Element
20+
>span : any
21+
>className : any
22+
>cx('class1', { class2: true }) : any
23+
>cx : any
24+
>'class1' : "class1"
25+
>{ class2: true } : { class2: boolean; }
26+
>class2 : boolean
27+
>true : true
28+
29+
</button>;
30+
>button : any
31+
32+
=== tests/cases/conformance/jsx/declaration.d.ts ===
33+
declare module "classnames";
34+
No type information for this code.
35+
No type information for this code.
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//// [tests/cases/conformance/jsx/correctlyMarkAliasAsReferences2.tsx] ////
2+
3+
//// [declaration.d.ts]
4+
declare module "classnames";
5+
6+
//// [0.tsx]
7+
///<reference path="declaration.d.ts" />
8+
import * as cx from 'classnames';
9+
import * as React from "react";
10+
11+
let buttonProps : {[attributeName: string]: ''}
12+
let k = <button {...buttonProps}>
13+
<span className={cx('class1', { class2: true })} />
14+
</button>;
15+
16+
17+
//// [0.js]
18+
///<reference path="declaration.d.ts" />
19+
import * as cx from 'classnames';
20+
import * as React from "react";
21+
let buttonProps;
22+
let k = React.createElement("button", Object.assign({}, buttonProps),
23+
React.createElement("span", { className: cx('class1', { class2: true }) }));
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
=== tests/cases/conformance/jsx/0.tsx ===
2+
///<reference path="declaration.d.ts" />
3+
import * as cx from 'classnames';
4+
>cx : Symbol(cx, Decl(0.tsx, 1, 6))
5+
6+
import * as React from "react";
7+
>React : Symbol(React, Decl(0.tsx, 2, 6))
8+
9+
let buttonProps : {[attributeName: string]: ''}
10+
>buttonProps : Symbol(buttonProps, Decl(0.tsx, 4, 3))
11+
>attributeName : Symbol(attributeName, Decl(0.tsx, 4, 20))
12+
13+
let k = <button {...buttonProps}>
14+
>k : Symbol(k, Decl(0.tsx, 5, 3))
15+
>button : Symbol(JSX.IntrinsicElements.button, Decl(react.d.ts, 2385, 43))
16+
>buttonProps : Symbol(buttonProps, Decl(0.tsx, 4, 3))
17+
18+
<span className={cx('class1', { class2: true })} />
19+
>span : Symbol(JSX.IntrinsicElements.span, Decl(react.d.ts, 2460, 51))
20+
>className : Symbol(className, Decl(0.tsx, 6, 17))
21+
>cx : Symbol(cx, Decl(0.tsx, 1, 6))
22+
>class2 : Symbol(class2, Decl(0.tsx, 6, 43))
23+
24+
</button>;
25+
>button : Symbol(JSX.IntrinsicElements.button, Decl(react.d.ts, 2385, 43))
26+
27+
=== tests/cases/conformance/jsx/declaration.d.ts ===
28+
declare module "classnames";
29+
No type information for this code.
30+
No type information for this code.
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
=== tests/cases/conformance/jsx/0.tsx ===
2+
///<reference path="declaration.d.ts" />
3+
import * as cx from 'classnames';
4+
>cx : any
5+
6+
import * as React from "react";
7+
>React : typeof React
8+
9+
let buttonProps : {[attributeName: string]: ''}
10+
>buttonProps : { [attributeName: string]: ""; }
11+
>attributeName : string
12+
13+
let k = <button {...buttonProps}>
14+
>k : JSX.Element
15+
><button {...buttonProps}> <span className={cx('class1', { class2: true })} /> </button> : JSX.Element
16+
>button : any
17+
>buttonProps : { [attributeName: string]: ""; }
18+
19+
<span className={cx('class1', { class2: true })} />
20+
><span className={cx('class1', { class2: true })} /> : JSX.Element
21+
>span : any
22+
>className : any
23+
>cx('class1', { class2: true }) : any
24+
>cx : any
25+
>'class1' : "class1"
26+
>{ class2: true } : { class2: boolean; }
27+
>class2 : boolean
28+
>true : true
29+
30+
</button>;
31+
>button : any
32+
33+
=== tests/cases/conformance/jsx/declaration.d.ts ===
34+
declare module "classnames";
35+
No type information for this code.
36+
No type information for this code.
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//// [tests/cases/conformance/jsx/correctlyMarkAliasAsReferences3.tsx] ////
2+
3+
//// [declaration.d.ts]
4+
declare module "classnames";
5+
6+
//// [0.tsx]
7+
///<reference path="declaration.d.ts" />
8+
import * as cx from 'classnames';
9+
import * as React from "react";
10+
11+
let buttonProps;
12+
let k = <button {...buttonProps}>
13+
<span className={cx('class1', { class2: true })} />
14+
</button>;
15+
16+
17+
//// [0.js]
18+
///<reference path="declaration.d.ts" />
19+
import * as cx from 'classnames';
20+
import * as React from "react";
21+
let buttonProps;
22+
let k = React.createElement("button", Object.assign({}, buttonProps),
23+
React.createElement("span", { className: cx('class1', { class2: true }) }));
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
=== tests/cases/conformance/jsx/0.tsx ===
2+
///<reference path="declaration.d.ts" />
3+
import * as cx from 'classnames';
4+
>cx : Symbol(cx, Decl(0.tsx, 1, 6))
5+
6+
import * as React from "react";
7+
>React : Symbol(React, Decl(0.tsx, 2, 6))
8+
9+
let buttonProps;
10+
>buttonProps : Symbol(buttonProps, Decl(0.tsx, 4, 3))
11+
12+
let k = <button {...buttonProps}>
13+
>k : Symbol(k, Decl(0.tsx, 5, 3))
14+
>button : Symbol(JSX.IntrinsicElements.button, Decl(react.d.ts, 2385, 43))
15+
>buttonProps : Symbol(buttonProps, Decl(0.tsx, 4, 3))
16+
17+
<span className={cx('class1', { class2: true })} />
18+
>span : Symbol(JSX.IntrinsicElements.span, Decl(react.d.ts, 2460, 51))
19+
>className : Symbol(className, Decl(0.tsx, 6, 17))
20+
>cx : Symbol(cx, Decl(0.tsx, 1, 6))
21+
>class2 : Symbol(class2, Decl(0.tsx, 6, 43))
22+
23+
</button>;
24+
>button : Symbol(JSX.IntrinsicElements.button, Decl(react.d.ts, 2385, 43))
25+
26+
=== tests/cases/conformance/jsx/declaration.d.ts ===
27+
declare module "classnames";
28+
No type information for this code.
29+
No type information for this code.
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
=== tests/cases/conformance/jsx/0.tsx ===
2+
///<reference path="declaration.d.ts" />
3+
import * as cx from 'classnames';
4+
>cx : any
5+
6+
import * as React from "react";
7+
>React : typeof React
8+
9+
let buttonProps;
10+
>buttonProps : any
11+
12+
let k = <button {...buttonProps}>
13+
>k : JSX.Element
14+
><button {...buttonProps}> <span className={cx('class1', { class2: true })} /> </button> : JSX.Element
15+
>button : any
16+
>buttonProps : undefined
17+
18+
<span className={cx('class1', { class2: true })} />
19+
><span className={cx('class1', { class2: true })} /> : JSX.Element
20+
>span : any
21+
>className : any
22+
>cx('class1', { class2: true }) : any
23+
>cx : any
24+
>'class1' : "class1"
25+
>{ class2: true } : { class2: boolean; }
26+
>class2 : boolean
27+
>true : true
28+
29+
</button>;
30+
>button : any
31+
32+
=== tests/cases/conformance/jsx/declaration.d.ts ===
33+
declare module "classnames";
34+
No type information for this code.
35+
No type information for this code.

0 commit comments

Comments
 (0)