Skip to content

Commit 41a7bf4

Browse files
authored
Fake up value declaration for synthetic jsx children symbol so they get excess property checked (#29359)
1 parent 9cd5f2d commit 41a7bf4

File tree

7 files changed

+188
-1
lines changed

7 files changed

+188
-1
lines changed

src/compiler/checker.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18550,6 +18550,10 @@ namespace ts {
1855018550
childrenPropSymbol.type = childrenTypes.length === 1 ?
1855118551
childrenTypes[0] :
1855218552
(getArrayLiteralTupleTypeIfApplicable(childrenTypes, childrenContextualType, /*hasRestElement*/ false) || createArrayType(getUnionType(childrenTypes)));
18553+
// Fake up a property declaration for the children
18554+
childrenPropSymbol.valueDeclaration = createPropertySignature(/*modifiers*/ undefined, unescapeLeadingUnderscores(jsxChildrenPropertyName), /*questionToken*/ undefined, /*type*/ undefined, /*initializer*/ undefined);
18555+
childrenPropSymbol.valueDeclaration.parent = attributes;
18556+
childrenPropSymbol.valueDeclaration.symbol = childrenPropSymbol;
1855318557
const childPropMap = createSymbolTable();
1855418558
childPropMap.set(jsxChildrenPropertyName, childrenPropSymbol);
1855518559
spread = getSpreadType(spread, createAnonymousType(attributes.symbol, childPropMap, emptyArray, emptyArray, /*stringIndexInfo*/ undefined, /*numberIndexInfo*/ undefined),
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
tests/cases/conformance/jsx/file.tsx(10,13): error TS2322: Type '{ children: Element; }' is not assignable to type 'IntrinsicAttributes'.
2+
Property 'children' does not exist on type 'IntrinsicAttributes'.
3+
tests/cases/conformance/jsx/file.tsx(11,13): error TS2322: Type '{ children: Element; key: string; }' is not assignable to type 'IntrinsicAttributes'.
4+
Property 'children' does not exist on type 'IntrinsicAttributes'.
5+
tests/cases/conformance/jsx/file.tsx(12,13): error TS2322: Type '{ children: Element[]; key: string; }' is not assignable to type 'IntrinsicAttributes'.
6+
Property 'children' does not exist on type 'IntrinsicAttributes'.
7+
8+
9+
==== tests/cases/conformance/jsx/file.tsx (3 errors) ====
10+
import React = require('react');
11+
12+
const Tag = (x: {}) => <div></div>;
13+
14+
// OK
15+
const k1 = <Tag />;
16+
const k2 = <Tag></Tag>;
17+
18+
// Not OK (excess children)
19+
const k3 = <Tag children={<div></div>} />;
20+
~~~
21+
!!! error TS2322: Type '{ children: Element; }' is not assignable to type 'IntrinsicAttributes'.
22+
!!! error TS2322: Property 'children' does not exist on type 'IntrinsicAttributes'.
23+
const k4 = <Tag key="1"><div></div></Tag>;
24+
~~~
25+
!!! error TS2322: Type '{ children: Element; key: string; }' is not assignable to type 'IntrinsicAttributes'.
26+
!!! error TS2322: Property 'children' does not exist on type 'IntrinsicAttributes'.
27+
const k5 = <Tag key="1"><div></div><div></div></Tag>;
28+
~~~
29+
!!! error TS2322: Type '{ children: Element[]; key: string; }' is not assignable to type 'IntrinsicAttributes'.
30+
!!! error TS2322: Property 'children' does not exist on type 'IntrinsicAttributes'.
31+
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
//// [file.tsx]
2+
import React = require('react');
3+
4+
const Tag = (x: {}) => <div></div>;
5+
6+
// OK
7+
const k1 = <Tag />;
8+
const k2 = <Tag></Tag>;
9+
10+
// Not OK (excess children)
11+
const k3 = <Tag children={<div></div>} />;
12+
const k4 = <Tag key="1"><div></div></Tag>;
13+
const k5 = <Tag key="1"><div></div><div></div></Tag>;
14+
15+
16+
//// [file.jsx]
17+
"use strict";
18+
exports.__esModule = true;
19+
var React = require("react");
20+
var Tag = function (x) { return <div></div>; };
21+
// OK
22+
var k1 = <Tag />;
23+
var k2 = <Tag></Tag>;
24+
// Not OK (excess children)
25+
var k3 = <Tag children={<div></div>}/>;
26+
var k4 = <Tag key="1"><div></div></Tag>;
27+
var k5 = <Tag key="1"><div></div><div></div></Tag>;
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
=== tests/cases/conformance/jsx/file.tsx ===
2+
import React = require('react');
3+
>React : Symbol(React, Decl(file.tsx, 0, 0))
4+
5+
const Tag = (x: {}) => <div></div>;
6+
>Tag : Symbol(Tag, Decl(file.tsx, 2, 5))
7+
>x : Symbol(x, Decl(file.tsx, 2, 13))
8+
>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2400, 45))
9+
>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2400, 45))
10+
11+
// OK
12+
const k1 = <Tag />;
13+
>k1 : Symbol(k1, Decl(file.tsx, 5, 5))
14+
>Tag : Symbol(Tag, Decl(file.tsx, 2, 5))
15+
16+
const k2 = <Tag></Tag>;
17+
>k2 : Symbol(k2, Decl(file.tsx, 6, 5))
18+
>Tag : Symbol(Tag, Decl(file.tsx, 2, 5))
19+
>Tag : Symbol(Tag, Decl(file.tsx, 2, 5))
20+
21+
// Not OK (excess children)
22+
const k3 = <Tag children={<div></div>} />;
23+
>k3 : Symbol(k3, Decl(file.tsx, 9, 5))
24+
>Tag : Symbol(Tag, Decl(file.tsx, 2, 5))
25+
>children : Symbol(children, Decl(file.tsx, 9, 15))
26+
>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2400, 45))
27+
>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2400, 45))
28+
29+
const k4 = <Tag key="1"><div></div></Tag>;
30+
>k4 : Symbol(k4, Decl(file.tsx, 10, 5))
31+
>Tag : Symbol(Tag, Decl(file.tsx, 2, 5))
32+
>key : Symbol(key, Decl(file.tsx, 10, 15))
33+
>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2400, 45))
34+
>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2400, 45))
35+
>Tag : Symbol(Tag, Decl(file.tsx, 2, 5))
36+
37+
const k5 = <Tag key="1"><div></div><div></div></Tag>;
38+
>k5 : Symbol(k5, Decl(file.tsx, 11, 5))
39+
>Tag : Symbol(Tag, Decl(file.tsx, 2, 5))
40+
>key : Symbol(key, Decl(file.tsx, 11, 15))
41+
>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2400, 45))
42+
>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2400, 45))
43+
>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2400, 45))
44+
>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2400, 45))
45+
>Tag : Symbol(Tag, Decl(file.tsx, 2, 5))
46+
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
=== tests/cases/conformance/jsx/file.tsx ===
2+
import React = require('react');
3+
>React : typeof React
4+
5+
const Tag = (x: {}) => <div></div>;
6+
>Tag : (x: {}) => JSX.Element
7+
>(x: {}) => <div></div> : (x: {}) => JSX.Element
8+
>x : {}
9+
><div></div> : JSX.Element
10+
>div : any
11+
>div : any
12+
13+
// OK
14+
const k1 = <Tag />;
15+
>k1 : JSX.Element
16+
><Tag /> : JSX.Element
17+
>Tag : (x: {}) => JSX.Element
18+
19+
const k2 = <Tag></Tag>;
20+
>k2 : JSX.Element
21+
><Tag></Tag> : JSX.Element
22+
>Tag : (x: {}) => JSX.Element
23+
>Tag : (x: {}) => JSX.Element
24+
25+
// Not OK (excess children)
26+
const k3 = <Tag children={<div></div>} />;
27+
>k3 : JSX.Element
28+
><Tag children={<div></div>} /> : JSX.Element
29+
>Tag : (x: {}) => JSX.Element
30+
>children : JSX.Element
31+
><div></div> : JSX.Element
32+
>div : any
33+
>div : any
34+
35+
const k4 = <Tag key="1"><div></div></Tag>;
36+
>k4 : JSX.Element
37+
><Tag key="1"><div></div></Tag> : JSX.Element
38+
>Tag : (x: {}) => JSX.Element
39+
>key : string
40+
><div></div> : JSX.Element
41+
>div : any
42+
>div : any
43+
>Tag : (x: {}) => JSX.Element
44+
45+
const k5 = <Tag key="1"><div></div><div></div></Tag>;
46+
>k5 : JSX.Element
47+
><Tag key="1"><div></div><div></div></Tag> : JSX.Element
48+
>Tag : (x: {}) => JSX.Element
49+
>key : string
50+
><div></div> : JSX.Element
51+
>div : any
52+
>div : any
53+
><div></div> : JSX.Element
54+
>div : any
55+
>div : any
56+
>Tag : (x: {}) => JSX.Element
57+

tests/baselines/reference/tsxStatelessFunctionComponentOverload4.errors.txt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@ tests/cases/conformance/jsx/file.tsx(26,40): error TS2322: Type 'string' is not
1212
tests/cases/conformance/jsx/file.tsx(33,32): error TS2322: Type 'string' is not assignable to type 'boolean'.
1313
tests/cases/conformance/jsx/file.tsx(34,29): error TS2322: Type 'string' is not assignable to type 'boolean'.
1414
tests/cases/conformance/jsx/file.tsx(35,29): error TS2322: Type 'string' is not assignable to type 'boolean'.
15+
tests/cases/conformance/jsx/file.tsx(36,29): error TS2322: Type 'string' is not assignable to type 'boolean'.
1516

1617

17-
==== tests/cases/conformance/jsx/file.tsx (10 errors) ====
18+
==== tests/cases/conformance/jsx/file.tsx (11 errors) ====
1819
import React = require('react')
1920
declare function OneThing(): JSX.Element;
2021
declare function OneThing(l: {yy: number, yy1: string}): JSX.Element;
@@ -82,4 +83,7 @@ tests/cases/conformance/jsx/file.tsx(35,29): error TS2322: Type 'string' is not
8283
!!! error TS2322: Type 'string' is not assignable to type 'boolean'.
8384
!!! related TS6500 tests/cases/conformance/jsx/file.tsx:30:38: The expected type comes from property 'y1' which is declared here on type 'IntrinsicAttributes & { y1: boolean; y2?: number; y3: boolean; }'
8485
const e4 = <TestingOptional y1="hello" y2={1000}>Hi</TestingOptional>
86+
~~
87+
!!! error TS2322: Type 'string' is not assignable to type 'boolean'.
88+
!!! related TS6500 tests/cases/conformance/jsx/file.tsx:30:38: The expected type comes from property 'y1' which is declared here on type 'IntrinsicAttributes & { y1: boolean; y2?: number; y3: boolean; }'
8589

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// @filename: file.tsx
2+
// @jsx: preserve
3+
// @noLib: true
4+
// @skipLibCheck: true
5+
// @libFiles: react.d.ts,lib.d.ts
6+
7+
import React = require('react');
8+
9+
const Tag = (x: {}) => <div></div>;
10+
11+
// OK
12+
const k1 = <Tag />;
13+
const k2 = <Tag></Tag>;
14+
15+
// Not OK (excess children)
16+
const k3 = <Tag children={<div></div>} />;
17+
const k4 = <Tag key="1"><div></div></Tag>;
18+
const k5 = <Tag key="1"><div></div><div></div></Tag>;

0 commit comments

Comments
 (0)