Fake up value declaration for synthetic jsx children symbol so they get excess property checked (#29359)

This commit is contained in:
Wesley Wigham 2019-01-15 22:31:57 -08:00 committed by GitHub
parent 9cd5f2dd3c
commit 41a7bf4b73
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 188 additions and 1 deletions

View File

@ -18550,6 +18550,10 @@ namespace ts {
childrenPropSymbol.type = childrenTypes.length === 1 ?
childrenTypes[0] :
(getArrayLiteralTupleTypeIfApplicable(childrenTypes, childrenContextualType, /*hasRestElement*/ false) || createArrayType(getUnionType(childrenTypes)));
// Fake up a property declaration for the children
childrenPropSymbol.valueDeclaration = createPropertySignature(/*modifiers*/ undefined, unescapeLeadingUnderscores(jsxChildrenPropertyName), /*questionToken*/ undefined, /*type*/ undefined, /*initializer*/ undefined);
childrenPropSymbol.valueDeclaration.parent = attributes;
childrenPropSymbol.valueDeclaration.symbol = childrenPropSymbol;
const childPropMap = createSymbolTable();
childPropMap.set(jsxChildrenPropertyName, childrenPropSymbol);
spread = getSpreadType(spread, createAnonymousType(attributes.symbol, childPropMap, emptyArray, emptyArray, /*stringIndexInfo*/ undefined, /*numberIndexInfo*/ undefined),

View File

@ -0,0 +1,31 @@
tests/cases/conformance/jsx/file.tsx(10,13): error TS2322: Type '{ children: Element; }' is not assignable to type 'IntrinsicAttributes'.
Property 'children' does not exist on type 'IntrinsicAttributes'.
tests/cases/conformance/jsx/file.tsx(11,13): error TS2322: Type '{ children: Element; key: string; }' is not assignable to type 'IntrinsicAttributes'.
Property 'children' does not exist on type 'IntrinsicAttributes'.
tests/cases/conformance/jsx/file.tsx(12,13): error TS2322: Type '{ children: Element[]; key: string; }' is not assignable to type 'IntrinsicAttributes'.
Property 'children' does not exist on type 'IntrinsicAttributes'.
==== tests/cases/conformance/jsx/file.tsx (3 errors) ====
import React = require('react');
const Tag = (x: {}) => <div></div>;
// OK
const k1 = <Tag />;
const k2 = <Tag></Tag>;
// Not OK (excess children)
const k3 = <Tag children={<div></div>} />;
~~~
!!! error TS2322: Type '{ children: Element; }' is not assignable to type 'IntrinsicAttributes'.
!!! error TS2322: Property 'children' does not exist on type 'IntrinsicAttributes'.
const k4 = <Tag key="1"><div></div></Tag>;
~~~
!!! error TS2322: Type '{ children: Element; key: string; }' is not assignable to type 'IntrinsicAttributes'.
!!! error TS2322: Property 'children' does not exist on type 'IntrinsicAttributes'.
const k5 = <Tag key="1"><div></div><div></div></Tag>;
~~~
!!! error TS2322: Type '{ children: Element[]; key: string; }' is not assignable to type 'IntrinsicAttributes'.
!!! error TS2322: Property 'children' does not exist on type 'IntrinsicAttributes'.

View File

@ -0,0 +1,27 @@
//// [file.tsx]
import React = require('react');
const Tag = (x: {}) => <div></div>;
// OK
const k1 = <Tag />;
const k2 = <Tag></Tag>;
// Not OK (excess children)
const k3 = <Tag children={<div></div>} />;
const k4 = <Tag key="1"><div></div></Tag>;
const k5 = <Tag key="1"><div></div><div></div></Tag>;
//// [file.jsx]
"use strict";
exports.__esModule = true;
var React = require("react");
var Tag = function (x) { return <div></div>; };
// OK
var k1 = <Tag />;
var k2 = <Tag></Tag>;
// Not OK (excess children)
var k3 = <Tag children={<div></div>}/>;
var k4 = <Tag key="1"><div></div></Tag>;
var k5 = <Tag key="1"><div></div><div></div></Tag>;

View File

@ -0,0 +1,46 @@
=== tests/cases/conformance/jsx/file.tsx ===
import React = require('react');
>React : Symbol(React, Decl(file.tsx, 0, 0))
const Tag = (x: {}) => <div></div>;
>Tag : Symbol(Tag, Decl(file.tsx, 2, 5))
>x : Symbol(x, Decl(file.tsx, 2, 13))
>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2400, 45))
>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2400, 45))
// OK
const k1 = <Tag />;
>k1 : Symbol(k1, Decl(file.tsx, 5, 5))
>Tag : Symbol(Tag, Decl(file.tsx, 2, 5))
const k2 = <Tag></Tag>;
>k2 : Symbol(k2, Decl(file.tsx, 6, 5))
>Tag : Symbol(Tag, Decl(file.tsx, 2, 5))
>Tag : Symbol(Tag, Decl(file.tsx, 2, 5))
// Not OK (excess children)
const k3 = <Tag children={<div></div>} />;
>k3 : Symbol(k3, Decl(file.tsx, 9, 5))
>Tag : Symbol(Tag, Decl(file.tsx, 2, 5))
>children : Symbol(children, Decl(file.tsx, 9, 15))
>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2400, 45))
>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2400, 45))
const k4 = <Tag key="1"><div></div></Tag>;
>k4 : Symbol(k4, Decl(file.tsx, 10, 5))
>Tag : Symbol(Tag, Decl(file.tsx, 2, 5))
>key : Symbol(key, Decl(file.tsx, 10, 15))
>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2400, 45))
>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2400, 45))
>Tag : Symbol(Tag, Decl(file.tsx, 2, 5))
const k5 = <Tag key="1"><div></div><div></div></Tag>;
>k5 : Symbol(k5, Decl(file.tsx, 11, 5))
>Tag : Symbol(Tag, Decl(file.tsx, 2, 5))
>key : Symbol(key, Decl(file.tsx, 11, 15))
>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2400, 45))
>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2400, 45))
>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2400, 45))
>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2400, 45))
>Tag : Symbol(Tag, Decl(file.tsx, 2, 5))

View File

@ -0,0 +1,57 @@
=== tests/cases/conformance/jsx/file.tsx ===
import React = require('react');
>React : typeof React
const Tag = (x: {}) => <div></div>;
>Tag : (x: {}) => JSX.Element
>(x: {}) => <div></div> : (x: {}) => JSX.Element
>x : {}
><div></div> : JSX.Element
>div : any
>div : any
// OK
const k1 = <Tag />;
>k1 : JSX.Element
><Tag /> : JSX.Element
>Tag : (x: {}) => JSX.Element
const k2 = <Tag></Tag>;
>k2 : JSX.Element
><Tag></Tag> : JSX.Element
>Tag : (x: {}) => JSX.Element
>Tag : (x: {}) => JSX.Element
// Not OK (excess children)
const k3 = <Tag children={<div></div>} />;
>k3 : JSX.Element
><Tag children={<div></div>} /> : JSX.Element
>Tag : (x: {}) => JSX.Element
>children : JSX.Element
><div></div> : JSX.Element
>div : any
>div : any
const k4 = <Tag key="1"><div></div></Tag>;
>k4 : JSX.Element
><Tag key="1"><div></div></Tag> : JSX.Element
>Tag : (x: {}) => JSX.Element
>key : string
><div></div> : JSX.Element
>div : any
>div : any
>Tag : (x: {}) => JSX.Element
const k5 = <Tag key="1"><div></div><div></div></Tag>;
>k5 : JSX.Element
><Tag key="1"><div></div><div></div></Tag> : JSX.Element
>Tag : (x: {}) => JSX.Element
>key : string
><div></div> : JSX.Element
>div : any
>div : any
><div></div> : JSX.Element
>div : any
>div : any
>Tag : (x: {}) => JSX.Element

View File

@ -12,9 +12,10 @@ tests/cases/conformance/jsx/file.tsx(26,40): error TS2322: Type 'string' is not
tests/cases/conformance/jsx/file.tsx(33,32): error TS2322: Type 'string' is not assignable to type 'boolean'.
tests/cases/conformance/jsx/file.tsx(34,29): error TS2322: Type 'string' is not assignable to type 'boolean'.
tests/cases/conformance/jsx/file.tsx(35,29): error TS2322: Type 'string' is not assignable to type 'boolean'.
tests/cases/conformance/jsx/file.tsx(36,29): error TS2322: Type 'string' is not assignable to type 'boolean'.
==== tests/cases/conformance/jsx/file.tsx (10 errors) ====
==== tests/cases/conformance/jsx/file.tsx (11 errors) ====
import React = require('react')
declare function OneThing(): JSX.Element;
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
!!! error TS2322: Type 'string' is not assignable to type 'boolean'.
!!! 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; }'
const e4 = <TestingOptional y1="hello" y2={1000}>Hi</TestingOptional>
~~
!!! error TS2322: Type 'string' is not assignable to type 'boolean'.
!!! 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; }'

View File

@ -0,0 +1,18 @@
// @filename: file.tsx
// @jsx: preserve
// @noLib: true
// @skipLibCheck: true
// @libFiles: react.d.ts,lib.d.ts
import React = require('react');
const Tag = (x: {}) => <div></div>;
// OK
const k1 = <Tag />;
const k2 = <Tag></Tag>;
// Not OK (excess children)
const k3 = <Tag children={<div></div>} />;
const k4 = <Tag key="1"><div></div></Tag>;
const k5 = <Tag key="1"><div></div><div></div></Tag>;