Skip to content

Commit

Permalink
fix(48556): throw an error on jsx spread attributes with an invalid t…
Browse files Browse the repository at this point in the history
  • Loading branch information
a-tarasyuk authored and Jack-Works committed Apr 22, 2022
1 parent 1611974 commit 9ef4563
Show file tree
Hide file tree
Showing 10 changed files with 165 additions and 3 deletions.
1 change: 1 addition & 0 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27986,6 +27986,7 @@ namespace ts {
}
}
else {
error(attributeDecl.expression, Diagnostics.Spread_types_may_only_be_created_from_object_types);
typeToIntersect = typeToIntersect ? getIntersectionType([typeToIntersect, exprType]) : exprType;
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
tests/cases/conformance/jsx/0.tsx(6,21): error TS2698: Spread types may only be created from object types.


==== tests/cases/conformance/jsx/0.tsx (1 errors) ====
///<reference path="declaration.d.ts" />
import * as cx from 'classnames';
import * as React from "react";

let buttonProps;
let k = <button {...buttonProps}>
~~~~~~~~~~~
!!! error TS2698: Spread types may only be created from object types.
<span className={cx('class1', { class2: true })} />
</button>;

==== tests/cases/conformance/jsx/declaration.d.ts (0 errors) ====
declare module "classnames";

Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
tests/cases/compiler/jsxExcessPropsAndAssignability.tsx(14,27): error TS2698: Spread types may only be created from object types.
tests/cases/compiler/jsxExcessPropsAndAssignability.tsx(16,6): error TS2322: Type 'ComposedComponentProps & { myProp: number; }' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<Component<WrapperComponentProps, any, any>> & Readonly<{ children?: ReactNode; }> & Readonly<WrapperComponentProps>'.
Type 'ComposedComponentProps & { myProp: number; }' is not assignable to type 'Readonly<WrapperComponentProps>'.
tests/cases/compiler/jsxExcessPropsAndAssignability.tsx(16,27): error TS2698: Spread types may only be created from object types.


==== tests/cases/compiler/jsxExcessPropsAndAssignability.tsx (1 errors) ====
==== tests/cases/compiler/jsxExcessPropsAndAssignability.tsx (3 errors) ====
/// <reference path="/.lib/react16.d.ts" />

import * as React from 'react';
Expand All @@ -17,10 +19,14 @@ tests/cases/compiler/jsxExcessPropsAndAssignability.tsx(16,6): error TS2322: Typ

// Expected no error, got none - good
<WrapperComponent {...props} myProp={'1000000'} />;
~~~~~
!!! error TS2698: Spread types may only be created from object types.
// Expected error, but got none - bad!
<WrapperComponent {...props} myProp={1000000} />;
~~~~~~~~~~~~~~~~
!!! error TS2322: Type 'ComposedComponentProps & { myProp: number; }' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<Component<WrapperComponentProps, any, any>> & Readonly<{ children?: ReactNode; }> & Readonly<WrapperComponentProps>'.
!!! error TS2322: Type 'ComposedComponentProps & { myProp: number; }' is not assignable to type 'Readonly<WrapperComponentProps>'.
~~~~~
!!! error TS2698: Spread types may only be created from object types.
};

Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ tests/cases/compiler/jsxNamespacePrefixInName.tsx(21,21): error TS1003: Identifi
tests/cases/compiler/jsxNamespacePrefixInName.tsx(22,26): error TS1003: Identifier expected.
tests/cases/compiler/jsxNamespacePrefixInName.tsx(22,27): error TS1003: Identifier expected.
tests/cases/compiler/jsxNamespacePrefixInName.tsx(22,29): error TS1005: '...' expected.
tests/cases/compiler/jsxNamespacePrefixInName.tsx(22,29): error TS2698: Spread types may only be created from object types.
tests/cases/compiler/jsxNamespacePrefixInName.tsx(24,21): error TS1109: Expression expected.
tests/cases/compiler/jsxNamespacePrefixInName.tsx(24,22): error TS1109: Expression expected.
tests/cases/compiler/jsxNamespacePrefixInName.tsx(24,25): error TS1005: ',' expected.
Expand All @@ -29,7 +30,7 @@ tests/cases/compiler/jsxNamespacePrefixInName.tsx(24,42): error TS1109: Expressi
tests/cases/compiler/jsxNamespacePrefixInName.tsx(25,24): error TS1003: Identifier expected.


==== tests/cases/compiler/jsxNamespacePrefixInName.tsx (29 errors) ====
==== tests/cases/compiler/jsxNamespacePrefixInName.tsx (30 errors) ====
var justElement1 = <a:element />;
var justElement2 = <a:element></a:element>;
var justElement3 = <a:element attr={"value"}></a:element>;
Expand Down Expand Up @@ -94,6 +95,8 @@ tests/cases/compiler/jsxNamespacePrefixInName.tsx(25,24): error TS1003: Identifi
!!! error TS1003: Identifier expected.
~~~~~~~
!!! error TS1005: '...' expected.
~~~~~~~
!!! error TS2698: Spread types may only be created from object types.

var beginOfIdent1 = <:a attr={"value"} />;
~
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ tests/cases/compiler/jsxNamespacePrefixInNameReact.tsx(23,21): error TS1003: Ide
tests/cases/compiler/jsxNamespacePrefixInNameReact.tsx(24,26): error TS1003: Identifier expected.
tests/cases/compiler/jsxNamespacePrefixInNameReact.tsx(24,27): error TS1003: Identifier expected.
tests/cases/compiler/jsxNamespacePrefixInNameReact.tsx(24,29): error TS1005: '...' expected.
tests/cases/compiler/jsxNamespacePrefixInNameReact.tsx(24,29): error TS2698: Spread types may only be created from object types.
tests/cases/compiler/jsxNamespacePrefixInNameReact.tsx(26,21): error TS1109: Expression expected.
tests/cases/compiler/jsxNamespacePrefixInNameReact.tsx(26,22): error TS1109: Expression expected.
tests/cases/compiler/jsxNamespacePrefixInNameReact.tsx(26,25): error TS1005: ',' expected.
Expand All @@ -29,7 +30,7 @@ tests/cases/compiler/jsxNamespacePrefixInNameReact.tsx(26,42): error TS1109: Exp
tests/cases/compiler/jsxNamespacePrefixInNameReact.tsx(27,24): error TS1003: Identifier expected.


==== tests/cases/compiler/jsxNamespacePrefixInNameReact.tsx (29 errors) ====
==== tests/cases/compiler/jsxNamespacePrefixInNameReact.tsx (30 errors) ====
declare var React: any;

var justElement1 = <a:element />;
Expand Down Expand Up @@ -96,6 +97,8 @@ tests/cases/compiler/jsxNamespacePrefixInNameReact.tsx(27,24): error TS1003: Ide
!!! error TS1003: Identifier expected.
~~~~~~~
!!! error TS1005: '...' expected.
~~~~~~~
!!! error TS2698: Spread types may only be created from object types.

var beginOfIdent1 = <:a attr={"value"} />;
~
Expand Down
24 changes: 24 additions & 0 deletions tests/baselines/reference/tsxSpreadInvalidType.errors.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
tests/cases/conformance/jsx/a.tsx(9,21): error TS2698: Spread types may only be created from object types.
tests/cases/conformance/jsx/a.tsx(10,21): error TS2698: Spread types may only be created from object types.
tests/cases/conformance/jsx/a.tsx(11,21): error TS2698: Spread types may only be created from object types.


==== tests/cases/conformance/jsx/a.tsx (3 errors) ====
namespace JSX {
export interface IntrinsicElements { [key: string]: any }
}

const a = {} as never;
const b = null;
const c = undefined;

const d = <div { ...a } />
~
!!! error TS2698: Spread types may only be created from object types.
const e = <div { ...b } />
~
!!! error TS2698: Spread types may only be created from object types.
const f = <div { ...c } />
~
!!! error TS2698: Spread types may only be created from object types.

22 changes: 22 additions & 0 deletions tests/baselines/reference/tsxSpreadInvalidType.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//// [a.tsx]
namespace JSX {
export interface IntrinsicElements { [key: string]: any }
}

const a = {} as never;
const b = null;
const c = undefined;

const d = <div { ...a } />
const e = <div { ...b } />
const f = <div { ...c } />


//// [a.jsx]
"use strict";
var a = {};
var b = null;
var c = undefined;
var d = <div {...a}/>;
var e = <div {...b}/>;
var f = <div {...c}/>;
34 changes: 34 additions & 0 deletions tests/baselines/reference/tsxSpreadInvalidType.symbols
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
=== tests/cases/conformance/jsx/a.tsx ===
namespace JSX {
>JSX : Symbol(JSX, Decl(a.tsx, 0, 0))

export interface IntrinsicElements { [key: string]: any }
>IntrinsicElements : Symbol(IntrinsicElements, Decl(a.tsx, 0, 15))
>key : Symbol(key, Decl(a.tsx, 1, 42))
}

const a = {} as never;
>a : Symbol(a, Decl(a.tsx, 4, 5))

const b = null;
>b : Symbol(b, Decl(a.tsx, 5, 5))

const c = undefined;
>c : Symbol(c, Decl(a.tsx, 6, 5))
>undefined : Symbol(undefined)

const d = <div { ...a } />
>d : Symbol(d, Decl(a.tsx, 8, 5))
>div : Symbol(JSX.IntrinsicElements, Decl(a.tsx, 0, 15))
>a : Symbol(a, Decl(a.tsx, 4, 5))

const e = <div { ...b } />
>e : Symbol(e, Decl(a.tsx, 9, 5))
>div : Symbol(JSX.IntrinsicElements, Decl(a.tsx, 0, 15))
>b : Symbol(b, Decl(a.tsx, 5, 5))

const f = <div { ...c } />
>f : Symbol(f, Decl(a.tsx, 10, 5))
>div : Symbol(JSX.IntrinsicElements, Decl(a.tsx, 0, 15))
>c : Symbol(c, Decl(a.tsx, 6, 5))

37 changes: 37 additions & 0 deletions tests/baselines/reference/tsxSpreadInvalidType.types
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
=== tests/cases/conformance/jsx/a.tsx ===
namespace JSX {
export interface IntrinsicElements { [key: string]: any }
>key : string
}

const a = {} as never;
>a : never
>{} as never : never
>{} : {}

const b = null;
>b : null
>null : null

const c = undefined;
>c : undefined
>undefined : undefined

const d = <div { ...a } />
>d : any
><div { ...a } /> : any
>div : any
>a : never

const e = <div { ...b } />
>e : any
><div { ...b } /> : any
>div : any
>b : null

const f = <div { ...c } />
>f : any
><div { ...c } /> : any
>div : any
>c : undefined

14 changes: 14 additions & 0 deletions tests/cases/conformance/jsx/tsxSpreadInvalidType.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// @jsx: preserve
// @strict: true
// @filename: a.tsx
namespace JSX {
export interface IntrinsicElements { [key: string]: any }
}

const a = {} as never;
const b = null;
const c = undefined;

const d = <div { ...a } />
const e = <div { ...b } />
const f = <div { ...c } />

0 comments on commit 9ef4563

Please sign in to comment.