Skip to content

Commit 975bc76

Browse files
authored
Merge pull request microsoft#15566 from Microsoft/master-fix15469
[Master] Port fix15469
2 parents 78df754 + f3a3198 commit 975bc76

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
@@ -13248,6 +13248,8 @@ namespace ts {
1324813248
let attributesTable = createMap<Symbol>();
1324913249
let spread: Type = emptyObjectType;
1325013250
let attributesArray: Symbol[] = [];
13251+
let hasSpreadAnyType = false;
13252+
1325113253
for (const attributeDecl of attributes.properties) {
1325213254
const member = attributeDecl.symbol;
1325313255
if (isJsxAttribute(attributeDecl)) {
@@ -13276,31 +13278,33 @@ namespace ts {
1327613278
const exprType = checkExpression(attributeDecl.expression);
1327713279
if (!isValidSpreadType(exprType)) {
1327813280
error(attributeDecl, Diagnostics.Spread_types_may_only_be_created_from_object_types);
13279-
return anyType;
13281+
hasSpreadAnyType = true;
1328013282
}
1328113283
if (isTypeAny(exprType)) {
13282-
return anyType;
13284+
hasSpreadAnyType = true;
1328313285
}
1328413286
spread = getSpreadType(spread, exprType);
1328513287
}
1328613288
}
1328713289

13288-
if (spread !== emptyObjectType) {
13289-
if (attributesArray.length > 0) {
13290-
spread = getSpreadType(spread, createJsxAttributesType(attributes.symbol, attributesTable));
13291-
attributesArray = [];
13292-
attributesTable = createMap<Symbol>();
13290+
if (!hasSpreadAnyType) {
13291+
if (spread !== emptyObjectType) {
13292+
if (attributesArray.length > 0) {
13293+
spread = getSpreadType(spread, createJsxAttributesType(attributes.symbol, attributesTable));
13294+
attributesArray = [];
13295+
attributesTable = createMap<Symbol>();
13296+
}
13297+
attributesArray = getPropertiesOfType(spread);
1329313298
}
13294-
attributesArray = getPropertiesOfType(spread);
13295-
}
1329613299

13297-
attributesTable = createMap<Symbol>();
13298-
if (attributesArray) {
13299-
forEach(attributesArray, (attr) => {
13300-
if (!filter || filter(attr)) {
13301-
attributesTable.set(attr.name, attr);
13302-
}
13303-
});
13300+
attributesTable = createMap<Symbol>();
13301+
if (attributesArray) {
13302+
forEach(attributesArray, (attr) => {
13303+
if (!filter || filter(attr)) {
13304+
attributesTable.set(attr.name, attr);
13305+
}
13306+
});
13307+
}
1330413308
}
1330513309

1330613310
// Handle children attribute
@@ -13324,7 +13328,7 @@ namespace ts {
1332413328
// Error if there is a attribute named "children" and children element.
1332513329
// This is because children element will overwrite the value from attributes
1332613330
const jsxChildrenPropertyName = getJsxElementChildrenPropertyname();
13327-
if (jsxChildrenPropertyName && jsxChildrenPropertyName !== "") {
13331+
if (!hasSpreadAnyType && jsxChildrenPropertyName && jsxChildrenPropertyName !== "") {
1332813332
if (attributesTable.has(jsxChildrenPropertyName)) {
1332913333
error(attributes, Diagnostics._0_are_specified_twice_The_attribute_named_0_will_be_overwritten, jsxChildrenPropertyName);
1333013334
}
@@ -13338,7 +13342,7 @@ namespace ts {
1333813342
}
1333913343
}
1334013344

13341-
return createJsxAttributesType(attributes.symbol, attributesTable);
13345+
return hasSpreadAnyType ? anyType : createJsxAttributesType(attributes.symbol, attributesTable);
1334213346

1334313347
/**
1334413348
* 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.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
//// [tests/cases/conformance/jsx/correctlyMarkAliasAsReferences4.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} className={cx('class1', { class2: true })} />;
13+
14+
//// [0.js]
15+
///<reference path="declaration.d.ts" />
16+
import * as cx from 'classnames';
17+
import * as React from "react";
18+
let buttonProps;
19+
let k = React.createElement("button", Object.assign({}, buttonProps, { className: cx('class1', { class2: true }) }));

0 commit comments

Comments
 (0)