mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-06-25 12:40:05 -05:00
Merge pull request #6104 from RyanCavanaugh/fix6029
Properly handle multiply-declared optional properties in JSX attr. type
This commit is contained in:
@@ -3768,11 +3768,14 @@ namespace ts {
|
||||
function createUnionOrIntersectionProperty(containingType: UnionOrIntersectionType, name: string): Symbol {
|
||||
const types = containingType.types;
|
||||
let props: Symbol[];
|
||||
// Flags we want to propagate to the result if they exist in all source symbols
|
||||
let commonFlags = (containingType.flags & TypeFlags.Intersection) ? SymbolFlags.Optional : SymbolFlags.None;
|
||||
for (const current of types) {
|
||||
const type = getApparentType(current);
|
||||
if (type !== unknownType) {
|
||||
const prop = getPropertyOfType(type, name);
|
||||
if (prop && !(getDeclarationFlagsFromSymbol(prop) & (NodeFlags.Private | NodeFlags.Protected))) {
|
||||
commonFlags &= prop.flags;
|
||||
if (!props) {
|
||||
props = [prop];
|
||||
}
|
||||
@@ -3800,7 +3803,12 @@ namespace ts {
|
||||
}
|
||||
propTypes.push(getTypeOfSymbol(prop));
|
||||
}
|
||||
const result = <TransientSymbol>createSymbol(SymbolFlags.Property | SymbolFlags.Transient | SymbolFlags.SyntheticProperty, name);
|
||||
const result = <TransientSymbol>createSymbol(
|
||||
SymbolFlags.Property |
|
||||
SymbolFlags.Transient |
|
||||
SymbolFlags.SyntheticProperty |
|
||||
commonFlags,
|
||||
name);
|
||||
result.containingType = containingType;
|
||||
result.declarations = declarations;
|
||||
result.type = containingType.flags & TypeFlags.Union ? getUnionType(propTypes) : getIntersectionType(propTypes);
|
||||
@@ -8356,9 +8364,9 @@ namespace ts {
|
||||
// Props is of type 'any' or unknown
|
||||
return links.resolvedJsxType = attributesType;
|
||||
}
|
||||
else if (!(attributesType.flags & TypeFlags.ObjectType)) {
|
||||
// Props is not an object type
|
||||
error(node.tagName, Diagnostics.JSX_element_attributes_type_0_must_be_an_object_type, typeToString(attributesType));
|
||||
else if (attributesType.flags & TypeFlags.Union) {
|
||||
// Props cannot be a union type
|
||||
error(node.tagName, Diagnostics.JSX_element_attributes_type_0_may_not_be_a_union_type, typeToString(attributesType));
|
||||
return links.resolvedJsxType = anyType;
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -1691,7 +1691,7 @@
|
||||
"category": "Error",
|
||||
"code": 2528
|
||||
},
|
||||
"JSX element attributes type '{0}' must be an object type.": {
|
||||
"JSX element attributes type '{0}' may not be a union type.": {
|
||||
"category": "Error",
|
||||
"code": 2600
|
||||
},
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
tests/cases/conformance/jsx/file.tsx(11,22): error TS2339: Property 'bar' does not exist on type 'IntrinsicAttributes & { ref?: string; }'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/jsx/react.d.ts (0 errors) ====
|
||||
|
||||
declare module JSX {
|
||||
interface Element { }
|
||||
interface IntrinsicElements {
|
||||
}
|
||||
interface ElementAttributesProperty {
|
||||
props;
|
||||
}
|
||||
interface IntrinsicAttributes {
|
||||
ref?: string;
|
||||
}
|
||||
}
|
||||
|
||||
==== tests/cases/conformance/jsx/file.tsx (1 errors) ====
|
||||
class MyComponent {
|
||||
render() {
|
||||
}
|
||||
|
||||
props: {
|
||||
ref?: string;
|
||||
}
|
||||
}
|
||||
|
||||
// Should be an OK
|
||||
var x = <MyComponent bar='world' />;
|
||||
~~~
|
||||
!!! error TS2339: Property 'bar' does not exist on type 'IntrinsicAttributes & { ref?: string; }'.
|
||||
|
||||
|
||||
41
tests/baselines/reference/tsxAttributeResolution11.js
Normal file
41
tests/baselines/reference/tsxAttributeResolution11.js
Normal file
@@ -0,0 +1,41 @@
|
||||
//// [tests/cases/conformance/jsx/tsxAttributeResolution11.tsx] ////
|
||||
|
||||
//// [react.d.ts]
|
||||
|
||||
declare module JSX {
|
||||
interface Element { }
|
||||
interface IntrinsicElements {
|
||||
}
|
||||
interface ElementAttributesProperty {
|
||||
props;
|
||||
}
|
||||
interface IntrinsicAttributes {
|
||||
ref?: string;
|
||||
}
|
||||
}
|
||||
|
||||
//// [file.tsx]
|
||||
class MyComponent {
|
||||
render() {
|
||||
}
|
||||
|
||||
props: {
|
||||
ref?: string;
|
||||
}
|
||||
}
|
||||
|
||||
// Should be an OK
|
||||
var x = <MyComponent bar='world' />;
|
||||
|
||||
|
||||
|
||||
//// [file.jsx]
|
||||
var MyComponent = (function () {
|
||||
function MyComponent() {
|
||||
}
|
||||
MyComponent.prototype.render = function () {
|
||||
};
|
||||
return MyComponent;
|
||||
}());
|
||||
// Should be an OK
|
||||
var x = <MyComponent bar='world'/>;
|
||||
29
tests/cases/conformance/jsx/tsxAttributeResolution11.tsx
Normal file
29
tests/cases/conformance/jsx/tsxAttributeResolution11.tsx
Normal file
@@ -0,0 +1,29 @@
|
||||
//@jsx: preserve
|
||||
//@module: amd
|
||||
|
||||
//@filename: react.d.ts
|
||||
declare module JSX {
|
||||
interface Element { }
|
||||
interface IntrinsicElements {
|
||||
}
|
||||
interface ElementAttributesProperty {
|
||||
props;
|
||||
}
|
||||
interface IntrinsicAttributes {
|
||||
ref?: string;
|
||||
}
|
||||
}
|
||||
|
||||
//@filename: file.tsx
|
||||
class MyComponent {
|
||||
render() {
|
||||
}
|
||||
|
||||
props: {
|
||||
ref?: string;
|
||||
}
|
||||
}
|
||||
|
||||
// Should be an OK
|
||||
var x = <MyComponent bar='world' />;
|
||||
|
||||
Reference in New Issue
Block a user