Skip to content

Commit 2e466c6

Browse files
authored
Merge pull request #14122 from Microsoft/jsx-spread-calls-isValidSpreadType
call isValidSpreadType in createJsxAttributesTypeFromAttributesProperty
2 parents 0627881 + bef1f9e commit 2e466c6

File tree

5 files changed

+87
-3
lines changed

5 files changed

+87
-3
lines changed

src/compiler/checker.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12241,10 +12241,12 @@ namespace ts {
1224112241

1224212242
/**
1224312243
* Get attributes type of the JSX opening-like element. The result is from resolving "attributes" property of the opening-like element.
12244-
*
12244+
*
1224512245
* @param openingLikeElement a JSX opening-like element
1224612246
* @param filter a function to remove attributes that will not participate in checking whether attributes are assignable
1224712247
* @return an anonymous type (similar to the one returned by checkObjectLiteral) in which its properties are attributes property.
12248+
* @remarks Because this function calls getSpreadType, it needs to use the same checks as checkObjectLiteral,
12249+
* which also calls getSpreadType.
1224812250
*/
1224912251
function createJsxAttributesTypeFromAttributesProperty(openingLikeElement: JsxOpeningLikeElement, filter?: (symbol: Symbol) => boolean, contextualMapper?: TypeMapper) {
1225012252
const attributes = openingLikeElement.attributes;
@@ -12256,7 +12258,7 @@ namespace ts {
1225612258
if (isJsxAttribute(attributeDecl)) {
1225712259
const exprType = attributeDecl.initializer ?
1225812260
checkExpression(attributeDecl.initializer, contextualMapper) :
12259-
trueType; // <Elem attr /> is sugar for <Elem attr={true} />
12261+
trueType; // <Elem attr /> is sugar for <Elem attr={true} />
1226012262

1226112263
const attributeSymbol = <TransientSymbol>createSymbol(SymbolFlags.Property | SymbolFlags.Transient | member.flags, member.name);
1226212264
attributeSymbol.declarations = member.declarations;
@@ -12277,7 +12279,7 @@ namespace ts {
1227712279
attributesTable = createMap<Symbol>();
1227812280
}
1227912281
const exprType = checkExpression(attributeDecl.expression);
12280-
if (!(exprType.flags & (TypeFlags.Object | TypeFlags.Any))) {
12282+
if (!isValidSpreadType(exprType)) {
1228112283
error(attributeDecl, Diagnostics.Spread_types_may_only_be_created_from_object_types);
1228212284
return anyType;
1228312285
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
//// [spreadIntersectionJsx.tsx]
2+
const React: any = null;
3+
class A { a; }
4+
class C { c; }
5+
let intersected: A & C;
6+
let element = <div { ...intersected } />;
7+
8+
9+
//// [spreadIntersectionJsx.js]
10+
var __assign = (this && this.__assign) || Object.assign || function(t) {
11+
for (var s, i = 1, n = arguments.length; i < n; i++) {
12+
s = arguments[i];
13+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
14+
t[p] = s[p];
15+
}
16+
return t;
17+
};
18+
var React = null;
19+
var A = (function () {
20+
function A() {
21+
}
22+
return A;
23+
}());
24+
var C = (function () {
25+
function C() {
26+
}
27+
return C;
28+
}());
29+
var intersected;
30+
var element = React.createElement("div", __assign({}, intersected));
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
=== tests/cases/compiler/spreadIntersectionJsx.tsx ===
2+
const React: any = null;
3+
>React : Symbol(React, Decl(spreadIntersectionJsx.tsx, 0, 5))
4+
5+
class A { a; }
6+
>A : Symbol(A, Decl(spreadIntersectionJsx.tsx, 0, 24))
7+
>a : Symbol(A.a, Decl(spreadIntersectionJsx.tsx, 1, 9))
8+
9+
class C { c; }
10+
>C : Symbol(C, Decl(spreadIntersectionJsx.tsx, 1, 14))
11+
>c : Symbol(C.c, Decl(spreadIntersectionJsx.tsx, 2, 9))
12+
13+
let intersected: A & C;
14+
>intersected : Symbol(intersected, Decl(spreadIntersectionJsx.tsx, 3, 3))
15+
>A : Symbol(A, Decl(spreadIntersectionJsx.tsx, 0, 24))
16+
>C : Symbol(C, Decl(spreadIntersectionJsx.tsx, 1, 14))
17+
18+
let element = <div { ...intersected } />;
19+
>element : Symbol(element, Decl(spreadIntersectionJsx.tsx, 4, 3))
20+
>div : Symbol(unknown)
21+
>intersected : Symbol(intersected, Decl(spreadIntersectionJsx.tsx, 3, 3))
22+
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
=== tests/cases/compiler/spreadIntersectionJsx.tsx ===
2+
const React: any = null;
3+
>React : any
4+
>null : null
5+
6+
class A { a; }
7+
>A : A
8+
>a : any
9+
10+
class C { c; }
11+
>C : C
12+
>c : any
13+
14+
let intersected: A & C;
15+
>intersected : A & C
16+
>A : A
17+
>C : C
18+
19+
let element = <div { ...intersected } />;
20+
>element : any
21+
><div { ...intersected } /> : any
22+
>div : any
23+
>intersected : A & C
24+
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// @jsx: react
2+
const React: any = null;
3+
class A { a; }
4+
class C { c; }
5+
let intersected: A & C;
6+
let element = <div { ...intersected } />;

0 commit comments

Comments
 (0)