Skip to content

Commit bef1f9e

Browse files
committed
call isValidSpreadType in createJsxAttributesTypeFromAttributesProperty
Previously, it only check for object and any types. This was the old check, so this change updates it to use isValidSpreadType.
1 parent c90040e commit bef1f9e

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)