diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 6340f6386a8..267da572737 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -15398,7 +15398,10 @@ namespace ts { if (hasSpreadAnyType) { return anyType; } - return typeToIntersect && spread !== emptyObjectType ? getIntersectionType([typeToIntersect, spread]) : (typeToIntersect || spread); + if (typeToIntersect && spread !== emptyObjectType) { + return getIntersectionType([typeToIntersect, spread]); + } + return typeToIntersect || (spread === emptyObjectType ? createJsxAttributesType() : spread); /** * Create anonymous type from given attributes symbol table. diff --git a/tests/baselines/reference/tsxAttributeResolution12.errors.txt b/tests/baselines/reference/tsxAttributeResolution12.errors.txt index 7ee4670dc65..3113eb833ba 100644 --- a/tests/baselines/reference/tsxAttributeResolution12.errors.txt +++ b/tests/baselines/reference/tsxAttributeResolution12.errors.txt @@ -3,6 +3,7 @@ tests/cases/conformance/jsx/file.tsx(25,10): error TS2322: Type '{}' is not assi Property 'reqd' is missing in type '{}'. tests/cases/conformance/jsx/file.tsx(28,10): error TS2322: Type '{}' is not assignable to type 'IntrinsicAttributes & { reqd: any; }'. Type '{}' is not assignable to type '{ reqd: any; }'. + Property 'reqd' is missing in type '{}'. ==== tests/cases/conformance/jsx/react.d.ts (0 errors) ==== @@ -54,5 +55,6 @@ tests/cases/conformance/jsx/file.tsx(28,10): error TS2322: Type '{}' is not assi ~~~~~~~~~~~~~~~~ !!! error TS2322: Type '{}' is not assignable to type 'IntrinsicAttributes & { reqd: any; }'. !!! error TS2322: Type '{}' is not assignable to type '{ reqd: any; }'. +!!! error TS2322: Property 'reqd' is missing in type '{}'. \ No newline at end of file diff --git a/tests/baselines/reference/tsxAttributesHasInferrableIndex.js b/tests/baselines/reference/tsxAttributesHasInferrableIndex.js new file mode 100644 index 00000000000..0cc23d34c40 --- /dev/null +++ b/tests/baselines/reference/tsxAttributesHasInferrableIndex.js @@ -0,0 +1,31 @@ +//// [tsxAttributesHasInferrableIndex.tsx] +type AttributeValue = number | string | Date | boolean; +interface Attributes { + [key: string]: AttributeValue; +} +function createElement(name: string, attributes: Attributes | undefined, ...contents: string[]) { + return name; +} +namespace createElement.JSX { + type Element = string; +} + +function Button(attributes: Attributes | undefined, contents: string[]) { + return ''; +} +const b = + + +//// [tsxAttributesHasInferrableIndex.js] +"use strict"; +function createElement(name, attributes) { + var contents = []; + for (var _i = 2; _i < arguments.length; _i++) { + contents[_i - 2] = arguments[_i]; + } + return name; +} +function Button(attributes, contents) { + return ''; +} +var b = createElement(Button, null); diff --git a/tests/baselines/reference/tsxAttributesHasInferrableIndex.symbols b/tests/baselines/reference/tsxAttributesHasInferrableIndex.symbols new file mode 100644 index 00000000000..f36c8ec1de8 --- /dev/null +++ b/tests/baselines/reference/tsxAttributesHasInferrableIndex.symbols @@ -0,0 +1,43 @@ +=== tests/cases/compiler/tsxAttributesHasInferrableIndex.tsx === +type AttributeValue = number | string | Date | boolean; +>AttributeValue : Symbol(AttributeValue, Decl(tsxAttributesHasInferrableIndex.tsx, 0, 0)) +>Date : Symbol(Date, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) + +interface Attributes { +>Attributes : Symbol(Attributes, Decl(tsxAttributesHasInferrableIndex.tsx, 0, 55)) + + [key: string]: AttributeValue; +>key : Symbol(key, Decl(tsxAttributesHasInferrableIndex.tsx, 2, 5)) +>AttributeValue : Symbol(AttributeValue, Decl(tsxAttributesHasInferrableIndex.tsx, 0, 0)) +} +function createElement(name: string, attributes: Attributes | undefined, ...contents: string[]) { +>createElement : Symbol(createElement, Decl(tsxAttributesHasInferrableIndex.tsx, 3, 1), Decl(tsxAttributesHasInferrableIndex.tsx, 6, 1)) +>name : Symbol(name, Decl(tsxAttributesHasInferrableIndex.tsx, 4, 23)) +>attributes : Symbol(attributes, Decl(tsxAttributesHasInferrableIndex.tsx, 4, 36)) +>Attributes : Symbol(Attributes, Decl(tsxAttributesHasInferrableIndex.tsx, 0, 55)) +>contents : Symbol(contents, Decl(tsxAttributesHasInferrableIndex.tsx, 4, 72)) + + return name; +>name : Symbol(name, Decl(tsxAttributesHasInferrableIndex.tsx, 4, 23)) +} +namespace createElement.JSX { +>createElement : Symbol(createElement, Decl(tsxAttributesHasInferrableIndex.tsx, 3, 1), Decl(tsxAttributesHasInferrableIndex.tsx, 6, 1)) +>JSX : Symbol(JSX, Decl(tsxAttributesHasInferrableIndex.tsx, 7, 24)) + + type Element = string; +>Element : Symbol(Element, Decl(tsxAttributesHasInferrableIndex.tsx, 7, 29)) +} + +function Button(attributes: Attributes | undefined, contents: string[]) { +>Button : Symbol(Button, Decl(tsxAttributesHasInferrableIndex.tsx, 9, 1)) +>attributes : Symbol(attributes, Decl(tsxAttributesHasInferrableIndex.tsx, 11, 16)) +>Attributes : Symbol(Attributes, Decl(tsxAttributesHasInferrableIndex.tsx, 0, 55)) +>contents : Symbol(contents, Decl(tsxAttributesHasInferrableIndex.tsx, 11, 51)) + + return ''; +} +const b = +>b : Symbol(b, Decl(tsxAttributesHasInferrableIndex.tsx, 14, 5)) +>Button : Symbol(Button, Decl(tsxAttributesHasInferrableIndex.tsx, 9, 1)) +>Button : Symbol(Button, Decl(tsxAttributesHasInferrableIndex.tsx, 9, 1)) + diff --git a/tests/baselines/reference/tsxAttributesHasInferrableIndex.types b/tests/baselines/reference/tsxAttributesHasInferrableIndex.types new file mode 100644 index 00000000000..91e577a07b4 --- /dev/null +++ b/tests/baselines/reference/tsxAttributesHasInferrableIndex.types @@ -0,0 +1,45 @@ +=== tests/cases/compiler/tsxAttributesHasInferrableIndex.tsx === +type AttributeValue = number | string | Date | boolean; +>AttributeValue : AttributeValue +>Date : Date + +interface Attributes { +>Attributes : Attributes + + [key: string]: AttributeValue; +>key : string +>AttributeValue : AttributeValue +} +function createElement(name: string, attributes: Attributes | undefined, ...contents: string[]) { +>createElement : (name: string, attributes: Attributes | undefined, ...contents: string[]) => string +>name : string +>attributes : Attributes | undefined +>Attributes : Attributes +>contents : string[] + + return name; +>name : string +} +namespace createElement.JSX { +>createElement : (name: string, attributes: Attributes | undefined, ...contents: string[]) => string +>JSX : any + + type Element = string; +>Element : string +} + +function Button(attributes: Attributes | undefined, contents: string[]) { +>Button : (attributes: Attributes | undefined, contents: string[]) => string +>attributes : Attributes | undefined +>Attributes : Attributes +>contents : string[] + + return ''; +>'' : "" +} +const b = +>b : any +> : any +>Button : (attributes: Attributes | undefined, contents: string[]) => string +>Button : (attributes: Attributes | undefined, contents: string[]) => string + diff --git a/tests/cases/compiler/tsxAttributesHasInferrableIndex.tsx b/tests/cases/compiler/tsxAttributesHasInferrableIndex.tsx new file mode 100644 index 00000000000..d5f43b0e712 --- /dev/null +++ b/tests/cases/compiler/tsxAttributesHasInferrableIndex.tsx @@ -0,0 +1,18 @@ +// @strict: true +// @jsx: react +// @jsxFactory: createElement +type AttributeValue = number | string | Date | boolean; +interface Attributes { + [key: string]: AttributeValue; +} +function createElement(name: string, attributes: Attributes | undefined, ...contents: string[]) { + return name; +} +namespace createElement.JSX { + type Element = string; +} + +function Button(attributes: Attributes | undefined, contents: string[]) { + return ''; +} +const b =