Merge pull request #21345 from Microsoft/fix-jsx-attribute-checking

Fix JSX attribute checking when spreading unions
This commit is contained in:
Nathan Shively-Sanders 2018-01-22 13:57:38 -08:00 committed by GitHub
commit 3735bb6fe7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 159 additions and 1 deletions

View File

@ -15310,7 +15310,7 @@ namespace ts {
// If the targetAttributesType is an emptyObjectType, indicating that there is no property named 'props' on this instance type.
// but there exists a sourceAttributesType, we need to explicitly give an error as normal assignability check allow excess properties and will pass.
if (targetAttributesType === emptyObjectType && (isTypeAny(sourceAttributesType) || (<ResolvedType>sourceAttributesType).properties.length > 0)) {
if (targetAttributesType === emptyObjectType && (isTypeAny(sourceAttributesType) || getPropertiesOfType(<ResolvedType>sourceAttributesType).length > 0)) {
error(openingLikeElement, Diagnostics.JSX_element_class_does_not_support_attributes_because_it_does_not_have_a_0_property, unescapeLeadingUnderscores(getJsxElementPropertiesName()));
}
else {

View File

@ -0,0 +1,47 @@
//// [file.tsx]
declare global {
namespace JSX {
interface Element {}
interface ElementAttributesProperty { props: {} }
}
}
declare var React: any;
export class Empty extends React.Component<{}, {}> {
render() {
return <div>Hello</div>;
}
}
declare const obj: { a: number | undefined } | undefined;
// OK
let unionedSpread = <Empty {...obj} />;
//// [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 __());
};
})();
exports.__esModule = true;
var Empty = /** @class */ (function (_super) {
__extends(Empty, _super);
function Empty() {
return _super !== null && _super.apply(this, arguments) || this;
}
Empty.prototype.render = function () {
return <div>Hello</div>;
};
return Empty;
}(React.Component));
exports.Empty = Empty;
// OK
var unionedSpread = <Empty {...obj}/>;

View File

@ -0,0 +1,41 @@
=== tests/cases/conformance/jsx/file.tsx ===
declare global {
>global : Symbol(global, Decl(file.tsx, 0, 0))
namespace JSX {
>JSX : Symbol(JSX, Decl(file.tsx, 0, 16))
interface Element {}
>Element : Symbol(Element, Decl(file.tsx, 1, 19))
interface ElementAttributesProperty { props: {} }
>ElementAttributesProperty : Symbol(ElementAttributesProperty, Decl(file.tsx, 2, 28))
>props : Symbol(ElementAttributesProperty.props, Decl(file.tsx, 3, 45))
}
}
declare var React: any;
>React : Symbol(React, Decl(file.tsx, 6, 11))
export class Empty extends React.Component<{}, {}> {
>Empty : Symbol(Empty, Decl(file.tsx, 6, 23))
>React : Symbol(React, Decl(file.tsx, 6, 11))
render() {
>render : Symbol(Empty.render, Decl(file.tsx, 8, 52))
return <div>Hello</div>;
>div : Symbol(unknown)
>div : Symbol(unknown)
}
}
declare const obj: { a: number | undefined } | undefined;
>obj : Symbol(obj, Decl(file.tsx, 14, 13))
>a : Symbol(a, Decl(file.tsx, 14, 20))
// OK
let unionedSpread = <Empty {...obj} />;
>unionedSpread : Symbol(unionedSpread, Decl(file.tsx, 17, 3))
>Empty : Symbol(Empty, Decl(file.tsx, 6, 23))
>obj : Symbol(obj, Decl(file.tsx, 14, 13))

View File

@ -0,0 +1,45 @@
=== tests/cases/conformance/jsx/file.tsx ===
declare global {
>global : any
namespace JSX {
>JSX : any
interface Element {}
>Element : Element
interface ElementAttributesProperty { props: {} }
>ElementAttributesProperty : ElementAttributesProperty
>props : {}
}
}
declare var React: any;
>React : any
export class Empty extends React.Component<{}, {}> {
>Empty : Empty
>React.Component : any
>React : any
>Component : any
render() {
>render : () => JSX.Element
return <div>Hello</div>;
><div>Hello</div> : JSX.Element
>div : any
>div : any
}
}
declare const obj: { a: number | undefined } | undefined;
>obj : { a: number | undefined; } | undefined
>a : number | undefined
// OK
let unionedSpread = <Empty {...obj} />;
>unionedSpread : JSX.Element
><Empty {...obj} /> : JSX.Element
>Empty : typeof Empty
>obj : { a: number | undefined; } | undefined

View File

@ -0,0 +1,25 @@
// @strictNullChecks: true
// @filename: file.tsx
// @jsx: preserve
// @noLib: true
// @skipLibCheck: true
// @libFiles: lib.d.ts
declare global {
namespace JSX {
interface Element {}
interface ElementAttributesProperty { props: {} }
}
}
declare var React: any;
export class Empty extends React.Component<{}, {}> {
render() {
return <div>Hello</div>;
}
}
declare const obj: { a: number | undefined } | undefined;
// OK
let unionedSpread = <Empty {...obj} />;