correctly handle the case when attributes type is empty object
This commit is contained in:
parent
328f5cc415
commit
e90a328562
15 changed files with 432 additions and 21 deletions
|
@ -7702,7 +7702,7 @@ namespace ts {
|
|||
if (type.flags & TypeFlags.Object) {
|
||||
const resolved = resolveStructuredTypeMembers(<ObjectType>type);
|
||||
if ((relation === assignableRelation || relation === comparableRelation) &&
|
||||
(type === globalObjectType || isEmptyObjectType(resolved))) {
|
||||
(type === globalObjectType || (!isComparingJsxAttributes && isEmptyObjectType(resolved)))) {
|
||||
return true;
|
||||
}
|
||||
else if (resolved.stringIndexInfo || (resolved.numberIndexInfo && isNumericLiteralName(name))) {
|
||||
|
@ -12200,15 +12200,17 @@ namespace ts {
|
|||
if (jsxElementType) {
|
||||
// We don't call getResolvedSignature here because we have already resolve the type of JSX Element.
|
||||
const callSignature = getResolvedJsxStatelessFunctionSignature(openingLikeElement, elementType, /*candidatesOutArray*/ undefined);
|
||||
const callReturnType = callSignature && getReturnTypeOfSignature(callSignature);
|
||||
let paramType = callReturnType && (callSignature.parameters.length === 0 ? emptyObjectType : getTypeOfSymbol(callSignature.parameters[0]));
|
||||
if (callReturnType && isTypeAssignableTo(callReturnType, jsxElementType)) {
|
||||
// Intersect in JSX.IntrinsicAttributes if it exists
|
||||
const intrinsicAttributes = getJsxType(JsxNames.IntrinsicAttributes);
|
||||
if (intrinsicAttributes !== unknownType) {
|
||||
paramType = intersectTypes(intrinsicAttributes, paramType);
|
||||
if (callSignature !== unknownSignature) {
|
||||
const callReturnType = callSignature && getReturnTypeOfSignature(callSignature);
|
||||
let paramType = callReturnType && (callSignature.parameters.length === 0 ? emptyObjectType : getTypeOfSymbol(callSignature.parameters[0]));
|
||||
if (callReturnType && isTypeAssignableTo(callReturnType, jsxElementType)) {
|
||||
// Intersect in JSX.IntrinsicAttributes if it exists
|
||||
const intrinsicAttributes = getJsxType(JsxNames.IntrinsicAttributes);
|
||||
if (intrinsicAttributes !== unknownType) {
|
||||
paramType = intersectTypes(intrinsicAttributes, paramType);
|
||||
}
|
||||
return paramType;
|
||||
}
|
||||
return paramType;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
tests/cases/conformance/jsx/file.tsx(12,21): error TS2322: Type '{ prop1: "hello"; }' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<BigGreeter> & {} & { children?: ReactNode; }'.
|
||||
Property 'prop1' does not exist on type 'IntrinsicAttributes & IntrinsicClassAttributes<BigGreeter> & {} & { children?: ReactNode; }'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/jsx/file.tsx (1 errors) ====
|
||||
|
||||
import React = require('react');
|
||||
|
||||
class BigGreeter extends React.Component<{ }, {}> {
|
||||
render() {
|
||||
return <div>Default hi</div>;
|
||||
}
|
||||
greeting: string;
|
||||
}
|
||||
|
||||
// Error
|
||||
let a = <BigGreeter prop1="hello" />
|
||||
~~~~~~~~~~~~~
|
||||
!!! error TS2322: Type '{ prop1: "hello"; }' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<BigGreeter> & {} & { children?: ReactNode; }'.
|
||||
!!! error TS2322: Property 'prop1' does not exist on type 'IntrinsicAttributes & IntrinsicClassAttributes<BigGreeter> & {} & { children?: ReactNode; }'.
|
||||
|
||||
// OK
|
||||
let b = <BigGreeter ref={(input) => { this.textInput = input; }} />
|
||||
let c = <BigGreeter data-extra="hi" />
|
47
tests/baselines/reference/tsxAttributeResolution15.js
Normal file
47
tests/baselines/reference/tsxAttributeResolution15.js
Normal file
|
@ -0,0 +1,47 @@
|
|||
//// [file.tsx]
|
||||
|
||||
import React = require('react');
|
||||
|
||||
class BigGreeter extends React.Component<{ }, {}> {
|
||||
render() {
|
||||
return <div>Default hi</div>;
|
||||
}
|
||||
greeting: string;
|
||||
}
|
||||
|
||||
// Error
|
||||
let a = <BigGreeter prop1="hello" />
|
||||
|
||||
// OK
|
||||
let b = <BigGreeter ref={(input) => { this.textInput = input; }} />
|
||||
let c = <BigGreeter data-extra="hi" />
|
||||
|
||||
//// [file.jsx]
|
||||
"use strict";
|
||||
var __extends = (this && this.__extends) || (function () {
|
||||
var extendStatics = Object.setPrototypeOf ||
|
||||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
||||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
|
||||
return function (d, b) {
|
||||
extendStatics(d, b);
|
||||
function __() { this.constructor = d; }
|
||||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||||
};
|
||||
})();
|
||||
var _this = this;
|
||||
var React = require("react");
|
||||
var BigGreeter = (function (_super) {
|
||||
__extends(BigGreeter, _super);
|
||||
function BigGreeter() {
|
||||
return _super !== null && _super.apply(this, arguments) || this;
|
||||
}
|
||||
BigGreeter.prototype.render = function () {
|
||||
return <div>Default hi</div>;
|
||||
};
|
||||
return BigGreeter;
|
||||
}(React.Component));
|
||||
// Error
|
||||
var a = <BigGreeter prop1="hello"/>;
|
||||
// OK
|
||||
var b = <BigGreeter ref={function (input) { _this.textInput = input; }}/>;
|
||||
var c = <BigGreeter data-extra="hi"/>;
|
|
@ -19,7 +19,21 @@ const obj: PoisonedProp = {
|
|||
};
|
||||
|
||||
// OK
|
||||
let p = <Poisoned {...obj} />;
|
||||
let p = <Poisoned {...obj} />;
|
||||
|
||||
class EmptyProp extends React.Component<{}, {}> {
|
||||
render() {
|
||||
return <div>Default hi</div>;
|
||||
}
|
||||
}
|
||||
|
||||
// OK
|
||||
let j: any;
|
||||
let e1 = <EmptyProp {...{}} />;
|
||||
let e2 = <EmptyProp {...j} />
|
||||
let e3 = <EmptyProp {...{ ref: (input) => { this.textInput = input; } }} />
|
||||
let e4 = <EmptyProp data-prop />
|
||||
let e5 = <EmptyProp {...{ "data-prop": true}} />
|
||||
|
||||
//// [file.jsx]
|
||||
"use strict";
|
||||
|
@ -33,6 +47,7 @@ var __extends = (this && this.__extends) || (function () {
|
|||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||||
};
|
||||
})();
|
||||
var _this = this;
|
||||
var React = require("react");
|
||||
var Poisoned = (function (_super) {
|
||||
__extends(Poisoned, _super);
|
||||
|
@ -50,3 +65,20 @@ var obj = {
|
|||
};
|
||||
// OK
|
||||
var p = <Poisoned {...obj}/>;
|
||||
var EmptyProp = (function (_super) {
|
||||
__extends(EmptyProp, _super);
|
||||
function EmptyProp() {
|
||||
return _super !== null && _super.apply(this, arguments) || this;
|
||||
}
|
||||
EmptyProp.prototype.render = function () {
|
||||
return <div>Default hi</div>;
|
||||
};
|
||||
return EmptyProp;
|
||||
}(React.Component));
|
||||
// OK
|
||||
var j;
|
||||
var e1 = <EmptyProp {...{}}/>;
|
||||
var e2 = <EmptyProp {...j}/>;
|
||||
var e3 = <EmptyProp {...{ ref: function (input) { _this.textInput = input; } }}/>;
|
||||
var e4 = <EmptyProp data-prop/>;
|
||||
var e5 = <EmptyProp {...{ "data-prop": true }}/>;
|
||||
|
|
|
@ -47,3 +47,47 @@ let p = <Poisoned {...obj} />;
|
|||
>Poisoned : Symbol(Poisoned, Decl(file.tsx, 6, 1))
|
||||
>obj : Symbol(obj, Decl(file.tsx, 14, 5))
|
||||
|
||||
class EmptyProp extends React.Component<{}, {}> {
|
||||
>EmptyProp : Symbol(EmptyProp, Decl(file.tsx, 20, 30))
|
||||
>React.Component : Symbol(React.Component, Decl(react.d.ts, 158, 55))
|
||||
>React : Symbol(React, Decl(file.tsx, 0, 0))
|
||||
>Component : Symbol(React.Component, Decl(react.d.ts, 158, 55))
|
||||
|
||||
render() {
|
||||
>render : Symbol(EmptyProp.render, Decl(file.tsx, 22, 49))
|
||||
|
||||
return <div>Default hi</div>;
|
||||
>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2397, 45))
|
||||
>div : Symbol(JSX.IntrinsicElements.div, Decl(react.d.ts, 2397, 45))
|
||||
}
|
||||
}
|
||||
|
||||
// OK
|
||||
let j: any;
|
||||
>j : Symbol(j, Decl(file.tsx, 29, 3))
|
||||
|
||||
let e1 = <EmptyProp {...{}} />;
|
||||
>e1 : Symbol(e1, Decl(file.tsx, 30, 3))
|
||||
>EmptyProp : Symbol(EmptyProp, Decl(file.tsx, 20, 30))
|
||||
|
||||
let e2 = <EmptyProp {...j} />
|
||||
>e2 : Symbol(e2, Decl(file.tsx, 31, 3))
|
||||
>EmptyProp : Symbol(EmptyProp, Decl(file.tsx, 20, 30))
|
||||
>j : Symbol(j, Decl(file.tsx, 29, 3))
|
||||
|
||||
let e3 = <EmptyProp {...{ ref: (input) => { this.textInput = input; } }} />
|
||||
>e3 : Symbol(e3, Decl(file.tsx, 32, 3))
|
||||
>EmptyProp : Symbol(EmptyProp, Decl(file.tsx, 20, 30))
|
||||
>ref : Symbol(ref, Decl(file.tsx, 32, 25))
|
||||
>input : Symbol(input, Decl(file.tsx, 32, 32))
|
||||
>input : Symbol(input, Decl(file.tsx, 32, 32))
|
||||
|
||||
let e4 = <EmptyProp data-prop />
|
||||
>e4 : Symbol(e4, Decl(file.tsx, 33, 3))
|
||||
>EmptyProp : Symbol(EmptyProp, Decl(file.tsx, 20, 30))
|
||||
>data-prop : Symbol(data-prop, Decl(file.tsx, 33, 19))
|
||||
|
||||
let e5 = <EmptyProp {...{ "data-prop": true}} />
|
||||
>e5 : Symbol(e5, Decl(file.tsx, 34, 3))
|
||||
>EmptyProp : Symbol(EmptyProp, Decl(file.tsx, 20, 30))
|
||||
|
||||
|
|
|
@ -52,3 +52,62 @@ let p = <Poisoned {...obj} />;
|
|||
>Poisoned : typeof Poisoned
|
||||
>obj : PoisonedProp
|
||||
|
||||
class EmptyProp extends React.Component<{}, {}> {
|
||||
>EmptyProp : EmptyProp
|
||||
>React.Component : React.Component<{}, {}>
|
||||
>React : typeof React
|
||||
>Component : typeof React.Component
|
||||
|
||||
render() {
|
||||
>render : () => JSX.Element
|
||||
|
||||
return <div>Default hi</div>;
|
||||
><div>Default hi</div> : JSX.Element
|
||||
>div : any
|
||||
>div : any
|
||||
}
|
||||
}
|
||||
|
||||
// OK
|
||||
let j: any;
|
||||
>j : any
|
||||
|
||||
let e1 = <EmptyProp {...{}} />;
|
||||
>e1 : JSX.Element
|
||||
><EmptyProp {...{}} /> : JSX.Element
|
||||
>EmptyProp : typeof EmptyProp
|
||||
>{} : {}
|
||||
|
||||
let e2 = <EmptyProp {...j} />
|
||||
>e2 : JSX.Element
|
||||
><EmptyProp {...j} /> : JSX.Element
|
||||
>EmptyProp : typeof EmptyProp
|
||||
>j : any
|
||||
|
||||
let e3 = <EmptyProp {...{ ref: (input) => { this.textInput = input; } }} />
|
||||
>e3 : JSX.Element
|
||||
><EmptyProp {...{ ref: (input) => { this.textInput = input; } }} /> : JSX.Element
|
||||
>EmptyProp : typeof EmptyProp
|
||||
>{ ref: (input) => { this.textInput = input; } } : { ref: (input: EmptyProp) => void; }
|
||||
>ref : (input: EmptyProp) => void
|
||||
>(input) => { this.textInput = input; } : (input: EmptyProp) => void
|
||||
>input : EmptyProp
|
||||
>this.textInput = input : EmptyProp
|
||||
>this.textInput : any
|
||||
>this : any
|
||||
>textInput : any
|
||||
>input : EmptyProp
|
||||
|
||||
let e4 = <EmptyProp data-prop />
|
||||
>e4 : JSX.Element
|
||||
><EmptyProp data-prop /> : JSX.Element
|
||||
>EmptyProp : typeof EmptyProp
|
||||
>data-prop : true
|
||||
|
||||
let e5 = <EmptyProp {...{ "data-prop": true}} />
|
||||
>e5 : JSX.Element
|
||||
><EmptyProp {...{ "data-prop": true}} /> : JSX.Element
|
||||
>EmptyProp : typeof EmptyProp
|
||||
>{ "data-prop": true} : { "data-prop": boolean; }
|
||||
>true : true
|
||||
|
||||
|
|
|
@ -2,9 +2,11 @@ tests/cases/conformance/jsx/file.tsx(21,19): error TS2322: Type '{ x: string; y:
|
|||
Type '{ x: string; y: number; }' is not assignable to type 'PoisonedProp'.
|
||||
Types of property 'y' are incompatible.
|
||||
Type 'number' is not assignable to type '2'.
|
||||
tests/cases/conformance/jsx/file.tsx(34,20): error TS2322: Type '{ prop1: boolean; }' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<EmptyProp> & {} & { children?: ReactNode; }'.
|
||||
Property 'prop1' does not exist on type 'IntrinsicAttributes & IntrinsicClassAttributes<EmptyProp> & {} & { children?: ReactNode; }'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/jsx/file.tsx (1 errors) ====
|
||||
==== tests/cases/conformance/jsx/file.tsx (2 errors) ====
|
||||
|
||||
import React = require('react');
|
||||
|
||||
|
@ -30,4 +32,20 @@ tests/cases/conformance/jsx/file.tsx(21,19): error TS2322: Type '{ x: string; y:
|
|||
!!! error TS2322: Type '{ x: string; y: number; }' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<Poisoned> & PoisonedProp & { children?: ReactNode; }'.
|
||||
!!! error TS2322: Type '{ x: string; y: number; }' is not assignable to type 'PoisonedProp'.
|
||||
!!! error TS2322: Types of property 'y' are incompatible.
|
||||
!!! error TS2322: Type 'number' is not assignable to type '2'.
|
||||
!!! error TS2322: Type 'number' is not assignable to type '2'.
|
||||
|
||||
class EmptyProp extends React.Component<{}, {}> {
|
||||
render() {
|
||||
return <div>Default hi</div>;
|
||||
}
|
||||
greeting: string;
|
||||
}
|
||||
|
||||
let o = {
|
||||
prop1: false
|
||||
}
|
||||
// Error
|
||||
let e = <EmptyProp {...o} />;
|
||||
~~~~~~
|
||||
!!! error TS2322: Type '{ prop1: boolean; }' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<EmptyProp> & {} & { children?: ReactNode; }'.
|
||||
!!! error TS2322: Property 'prop1' does not exist on type 'IntrinsicAttributes & IntrinsicClassAttributes<EmptyProp> & {} & { children?: ReactNode; }'.
|
|
@ -19,7 +19,20 @@ let obj = {
|
|||
};
|
||||
|
||||
// Error as "obj" has type { x: string; y: number }
|
||||
let p = <Poisoned {...obj} />;
|
||||
let p = <Poisoned {...obj} />;
|
||||
|
||||
class EmptyProp extends React.Component<{}, {}> {
|
||||
render() {
|
||||
return <div>Default hi</div>;
|
||||
}
|
||||
greeting: string;
|
||||
}
|
||||
|
||||
let o = {
|
||||
prop1: false
|
||||
}
|
||||
// Error
|
||||
let e = <EmptyProp {...o} />;
|
||||
|
||||
//// [file.jsx]
|
||||
"use strict";
|
||||
|
@ -50,3 +63,18 @@ var obj = {
|
|||
};
|
||||
// Error as "obj" has type { x: string; y: number }
|
||||
var p = <Poisoned {...obj}/>;
|
||||
var EmptyProp = (function (_super) {
|
||||
__extends(EmptyProp, _super);
|
||||
function EmptyProp() {
|
||||
return _super !== null && _super.apply(this, arguments) || this;
|
||||
}
|
||||
EmptyProp.prototype.render = function () {
|
||||
return <div>Default hi</div>;
|
||||
};
|
||||
return EmptyProp;
|
||||
}(React.Component));
|
||||
var o = {
|
||||
prop1: false
|
||||
};
|
||||
// Error
|
||||
var e = <EmptyProp {...o}/>;
|
||||
|
|
|
@ -1,17 +1,28 @@
|
|||
tests/cases/conformance/jsx/file.tsx(16,16): error TS2322: Type '{ naaame: "world"; }' is not assignable to type 'IntrinsicAttributes & { name: string; }'.
|
||||
tests/cases/conformance/jsx/file.tsx(20,16): error TS2322: Type '{ naaame: "world"; }' is not assignable to type 'IntrinsicAttributes & { name: string; }'.
|
||||
Property 'naaame' does not exist on type 'IntrinsicAttributes & { name: string; }'.
|
||||
tests/cases/conformance/jsx/file.tsx(24,15): error TS2322: Type '{ name: 42; }' is not assignable to type 'IntrinsicAttributes & { name?: string; }'.
|
||||
tests/cases/conformance/jsx/file.tsx(28,15): error TS2322: Type '{ name: 42; }' is not assignable to type 'IntrinsicAttributes & { name?: string; }'.
|
||||
Type '{ name: 42; }' is not assignable to type '{ name?: string; }'.
|
||||
Types of property 'name' are incompatible.
|
||||
Type '42' is not assignable to type 'string'.
|
||||
tests/cases/conformance/jsx/file.tsx(26,15): error TS2322: Type '{ naaaaaaame: "no"; }' is not assignable to type 'IntrinsicAttributes & { name?: string; }'.
|
||||
tests/cases/conformance/jsx/file.tsx(30,15): error TS2322: Type '{ naaaaaaame: "no"; }' is not assignable to type 'IntrinsicAttributes & { name?: string; }'.
|
||||
Property 'naaaaaaame' does not exist on type 'IntrinsicAttributes & { name?: string; }'.
|
||||
tests/cases/conformance/jsx/file.tsx(31,23): error TS2322: Type '{}' is not assignable to type 'IntrinsicAttributes & { "prop-name": string; }'.
|
||||
tests/cases/conformance/jsx/file.tsx(35,23): error TS2322: Type '{}' is not assignable to type 'IntrinsicAttributes & { "prop-name": string; }'.
|
||||
Type '{}' is not assignable to type '{ "prop-name": string; }'.
|
||||
Property '"prop-name"' is missing in type '{}'.
|
||||
tests/cases/conformance/jsx/file.tsx(38,23): error TS2322: Type '{ prop1: true; }' is not assignable to type 'IntrinsicAttributes & {}'.
|
||||
Property 'prop1' does not exist on type 'IntrinsicAttributes & {}'.
|
||||
tests/cases/conformance/jsx/file.tsx(39,24): error TS2322: Type '{ ref: (x: any) => any; }' is not assignable to type 'IntrinsicAttributes & {}'.
|
||||
Property 'ref' does not exist on type 'IntrinsicAttributes & {}'.
|
||||
tests/cases/conformance/jsx/file.tsx(42,16): error TS1005: ',' expected.
|
||||
tests/cases/conformance/jsx/file.tsx(46,24): error TS2322: Type '{ prop1: boolean; }' is not assignable to type 'IntrinsicAttributes & {}'.
|
||||
Property 'prop1' does not exist on type 'IntrinsicAttributes & {}'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/jsx/file.tsx (4 errors) ====
|
||||
==== tests/cases/conformance/jsx/file.tsx (8 errors) ====
|
||||
|
||||
function EmptyPropSFC() {
|
||||
return <div> Default Greeting </div>;
|
||||
}
|
||||
|
||||
function Greet(x: {name: string}) {
|
||||
return <div>Hello, {x}</div>;
|
||||
|
@ -59,4 +70,34 @@ tests/cases/conformance/jsx/file.tsx(31,23): error TS2322: Type '{}' is not assi
|
|||
!!! error TS2322: Type '{}' is not assignable to type '{ "prop-name": string; }'.
|
||||
!!! error TS2322: Property '"prop-name"' is missing in type '{}'.
|
||||
|
||||
// Error
|
||||
let i = <EmptyPropSFC prop1 />
|
||||
~~~~~
|
||||
!!! error TS2322: Type '{ prop1: true; }' is not assignable to type 'IntrinsicAttributes & {}'.
|
||||
!!! error TS2322: Property 'prop1' does not exist on type 'IntrinsicAttributes & {}'.
|
||||
let i1 = <EmptyPropSFC ref={x => x.greeting.substr(10)} />
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
!!! error TS2322: Type '{ ref: (x: any) => any; }' is not assignable to type 'IntrinsicAttributes & {}'.
|
||||
!!! error TS2322: Property 'ref' does not exist on type 'IntrinsicAttributes & {}'.
|
||||
|
||||
let o = {
|
||||
prop1: true;
|
||||
~
|
||||
!!! error TS1005: ',' expected.
|
||||
}
|
||||
|
||||
// Error
|
||||
let i2 = <EmptyPropSFC {...o} />
|
||||
~~~~~~
|
||||
!!! error TS2322: Type '{ prop1: boolean; }' is not assignable to type 'IntrinsicAttributes & {}'.
|
||||
!!! error TS2322: Property 'prop1' does not exist on type 'IntrinsicAttributes & {}'.
|
||||
|
||||
let o1: any;
|
||||
// OK
|
||||
let j = <EmptyPropSFC {...o1} />
|
||||
let j1 = <EmptyPropSFC />
|
||||
let j2 = <EmptyPropSFC data-prop />
|
||||
let j3 = <EmptyPropSFC {...{}} />
|
||||
let j4 = <EmptyPropSFC {...{ "data-info": "hi"}} />
|
||||
|
||||
|
|
@ -1,5 +1,9 @@
|
|||
//// [file.tsx]
|
||||
|
||||
function EmptyPropSFC() {
|
||||
return <div> Default Greeting </div>;
|
||||
}
|
||||
|
||||
function Greet(x: {name: string}) {
|
||||
return <div>Hello, {x}</div>;
|
||||
}
|
||||
|
@ -31,9 +35,31 @@ let g = <MeetAndGreet prop-name="Bob" />;
|
|||
// Error
|
||||
let h = <MeetAndGreet extra-prop-name="World" />;
|
||||
|
||||
// Error
|
||||
let i = <EmptyPropSFC prop1 />
|
||||
let i1 = <EmptyPropSFC ref={x => x.greeting.substr(10)} />
|
||||
|
||||
let o = {
|
||||
prop1: true;
|
||||
}
|
||||
|
||||
// Error
|
||||
let i2 = <EmptyPropSFC {...o} />
|
||||
|
||||
let o1: any;
|
||||
// OK
|
||||
let j = <EmptyPropSFC {...o1} />
|
||||
let j1 = <EmptyPropSFC />
|
||||
let j2 = <EmptyPropSFC data-prop />
|
||||
let j3 = <EmptyPropSFC {...{}} />
|
||||
let j4 = <EmptyPropSFC {...{ "data-info": "hi"}} />
|
||||
|
||||
|
||||
|
||||
//// [file.jsx]
|
||||
function EmptyPropSFC() {
|
||||
return <div> Default Greeting </div>;
|
||||
}
|
||||
function Greet(x) {
|
||||
return <div>Hello, {x}</div>;
|
||||
}
|
||||
|
@ -62,3 +88,18 @@ var f = <Meet naaaaaaame='no'/>;
|
|||
var g = <MeetAndGreet prop-name="Bob"/>;
|
||||
// Error
|
||||
var h = <MeetAndGreet extra-prop-name="World"/>;
|
||||
// Error
|
||||
var i = <EmptyPropSFC prop1/>;
|
||||
var i1 = <EmptyPropSFC ref={function (x) { return x.greeting.substr(10); }}/>;
|
||||
var o = {
|
||||
prop1: true
|
||||
};
|
||||
// Error
|
||||
var i2 = <EmptyPropSFC {...o}/>;
|
||||
var o1;
|
||||
// OK
|
||||
var j = <EmptyPropSFC {...o1}/>;
|
||||
var j1 = <EmptyPropSFC />;
|
||||
var j2 = <EmptyPropSFC data-prop/>;
|
||||
var j3 = <EmptyPropSFC {...{}}/>;
|
||||
var j4 = <EmptyPropSFC {...{ "data-info": "hi" }}/>;
|
||||
|
|
|
@ -4,11 +4,13 @@ tests/cases/conformance/jsx/file.tsx(21,19): error TS2322: Type '{ func: (a: num
|
|||
Type '{ func: (a: number, b: string) => void; }' is not assignable to type '{ func: (arg: number) => void; }'.
|
||||
Types of property 'func' are incompatible.
|
||||
Type '(a: number, b: string) => void' is not assignable to type '(arg: number) => void'.
|
||||
tests/cases/conformance/jsx/file.tsx(32,9): error TS2605: JSX element type 'Element' is not a constructor function for JSX elements.
|
||||
Property 'render' is missing in type 'Element'.
|
||||
tests/cases/conformance/jsx/file.tsx(32,10): error TS2453: The type argument for type parameter 'T' cannot be inferred from the usage. Consider specifying the type arguments explicitly.
|
||||
Type argument candidate 'number' is not a valid type argument because it is not a supertype of candidate 'string'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/jsx/file.tsx (4 errors) ====
|
||||
==== tests/cases/conformance/jsx/file.tsx (5 errors) ====
|
||||
|
||||
import React = require('react')
|
||||
|
||||
|
@ -50,6 +52,9 @@ tests/cases/conformance/jsx/file.tsx(32,10): error TS2453: The type argument for
|
|||
|
||||
// Error
|
||||
let i = <InferParamComponent values={[1, 2, 3, 4]} selectHandler={(val: string) => { }} />;
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
!!! error TS2605: JSX element type 'Element' is not a constructor function for JSX elements.
|
||||
!!! error TS2605: Property 'render' is missing in type 'Element'.
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
!!! error TS2453: The type argument for type parameter 'T' cannot be inferred from the usage. Consider specifying the type arguments explicitly.
|
||||
!!! error TS2453: Type argument candidate 'number' is not a valid type argument because it is not a supertype of candidate 'string'.
|
||||
|
|
20
tests/cases/conformance/jsx/tsxAttributeResolution15.tsx
Normal file
20
tests/cases/conformance/jsx/tsxAttributeResolution15.tsx
Normal file
|
@ -0,0 +1,20 @@
|
|||
// @filename: file.tsx
|
||||
// @jsx: preserve
|
||||
// @noLib: true
|
||||
// @libFiles: react.d.ts,lib.d.ts
|
||||
|
||||
import React = require('react');
|
||||
|
||||
class BigGreeter extends React.Component<{ }, {}> {
|
||||
render() {
|
||||
return <div>Default hi</div>;
|
||||
}
|
||||
greeting: string;
|
||||
}
|
||||
|
||||
// Error
|
||||
let a = <BigGreeter prop1="hello" />
|
||||
|
||||
// OK
|
||||
let b = <BigGreeter ref={(input) => { this.textInput = input; }} />
|
||||
let c = <BigGreeter data-extra="hi" />
|
|
@ -22,4 +22,18 @@ const obj: PoisonedProp = {
|
|||
};
|
||||
|
||||
// OK
|
||||
let p = <Poisoned {...obj} />;
|
||||
let p = <Poisoned {...obj} />;
|
||||
|
||||
class EmptyProp extends React.Component<{}, {}> {
|
||||
render() {
|
||||
return <div>Default hi</div>;
|
||||
}
|
||||
}
|
||||
|
||||
// OK
|
||||
let j: any;
|
||||
let e1 = <EmptyProp {...{}} />;
|
||||
let e2 = <EmptyProp {...j} />
|
||||
let e3 = <EmptyProp {...{ ref: (input) => { this.textInput = input; } }} />
|
||||
let e4 = <EmptyProp data-prop />
|
||||
let e5 = <EmptyProp {...{ "data-prop": true}} />
|
|
@ -22,4 +22,17 @@ let obj = {
|
|||
};
|
||||
|
||||
// Error as "obj" has type { x: string; y: number }
|
||||
let p = <Poisoned {...obj} />;
|
||||
let p = <Poisoned {...obj} />;
|
||||
|
||||
class EmptyProp extends React.Component<{}, {}> {
|
||||
render() {
|
||||
return <div>Default hi</div>;
|
||||
}
|
||||
greeting: string;
|
||||
}
|
||||
|
||||
let o = {
|
||||
prop1: false
|
||||
}
|
||||
// Error
|
||||
let e = <EmptyProp {...o} />;
|
|
@ -3,6 +3,10 @@
|
|||
// @noLib: true
|
||||
// @libFiles: react.d.ts,lib.d.ts
|
||||
|
||||
function EmptyPropSFC() {
|
||||
return <div> Default Greeting </div>;
|
||||
}
|
||||
|
||||
function Greet(x: {name: string}) {
|
||||
return <div>Hello, {x}</div>;
|
||||
}
|
||||
|
@ -34,3 +38,22 @@ let g = <MeetAndGreet prop-name="Bob" />;
|
|||
// Error
|
||||
let h = <MeetAndGreet extra-prop-name="World" />;
|
||||
|
||||
// Error
|
||||
let i = <EmptyPropSFC prop1 />
|
||||
let i1 = <EmptyPropSFC ref={x => x.greeting.substr(10)} />
|
||||
|
||||
let o = {
|
||||
prop1: true;
|
||||
}
|
||||
|
||||
// Error
|
||||
let i2 = <EmptyPropSFC {...o} />
|
||||
|
||||
let o1: any;
|
||||
// OK
|
||||
let j = <EmptyPropSFC {...o1} />
|
||||
let j1 = <EmptyPropSFC />
|
||||
let j2 = <EmptyPropSFC data-prop />
|
||||
let j3 = <EmptyPropSFC {...{}} />
|
||||
let j4 = <EmptyPropSFC {...{ "data-info": "hi"}} />
|
||||
|
||||
|
|
Loading…
Reference in a new issue