Obey the excludeArgument parameter when checking JSX signature validity (#28002)

* Obey the excludeArgument parameter when checking JSX signature validity

* Fix conditional type extending any contextual types and accept baselines

* use flag check to also drop unknown from comparison for the same reason

* Slight refinement - make an intersection to ensure parameter constraints flow through contextual types when instantiated

* Format ternary more nicely
This commit is contained in:
Wesley Wigham
2018-10-22 16:36:11 -07:00
committed by GitHub
parent f701daf4e0
commit 0c36266706
11 changed files with 272 additions and 21 deletions

View File

@@ -7083,7 +7083,11 @@ namespace ts {
function getDefaultConstraintOfConditionalType(type: ConditionalType) {
if (!type.resolvedDefaultConstraint) {
const rootTrueType = type.root.trueType;
const rootTrueConstraint = rootTrueType.flags & TypeFlags.Substitution ? (<SubstitutionType>rootTrueType).substitute : rootTrueType;
const rootTrueConstraint = !(rootTrueType.flags & TypeFlags.Substitution)
? rootTrueType
: ((<SubstitutionType>rootTrueType).substitute).flags & TypeFlags.AnyOrUnknown
? (<SubstitutionType>rootTrueType).typeVariable
: getIntersectionType([(<SubstitutionType>rootTrueType).substitute, (<SubstitutionType>rootTrueType).typeVariable]);
type.resolvedDefaultConstraint = getUnionType([instantiateType(rootTrueConstraint, type.combinedMapper || type.mapper), getFalseTypeFromConditionalType(type)]);
}
return type.resolvedDefaultConstraint;
@@ -19163,12 +19167,12 @@ namespace ts {
* @param relation a relationship to check parameter and argument type
* @param excludeArgument
*/
function checkApplicableSignatureForJsxOpeningLikeElement(node: JsxOpeningLikeElement, signature: Signature, relation: Map<RelationComparisonResult>, reportErrors: boolean) {
function checkApplicableSignatureForJsxOpeningLikeElement(node: JsxOpeningLikeElement, signature: Signature, relation: Map<RelationComparisonResult>, excludeArgument: boolean[] | undefined, reportErrors: boolean) {
// Stateless function components can have maximum of three arguments: "props", "context", and "updater".
// However "context" and "updater" are implicit and can't be specify by users. Only the first parameter, props,
// can be specified by users through attributes property.
const paramType = getEffectiveFirstArgumentForJsxSignature(signature, node);
const attributesType = checkExpressionWithContextualType(node.attributes, paramType, /*contextualMapper*/ undefined);
const attributesType = checkExpressionWithContextualType(node.attributes, paramType, excludeArgument && excludeArgument[0] ? identityMapper : undefined);
return checkTypeRelatedToAndOptionallyElaborate(attributesType, paramType, relation, reportErrors ? node.tagName : undefined, node.attributes);
}
@@ -19180,7 +19184,7 @@ namespace ts {
excludeArgument: boolean[] | undefined,
reportErrors: boolean) {
if (isJsxOpeningLikeElement(node)) {
return checkApplicableSignatureForJsxOpeningLikeElement(node, signature, relation, reportErrors);
return checkApplicableSignatureForJsxOpeningLikeElement(node, signature, relation, excludeArgument, reportErrors);
}
const thisType = getThisTypeOfSignature(signature);
if (thisType && thisType !== voidType && node.kind !== SyntaxKind.NewExpression) {

View File

@@ -1,4 +1,6 @@
tests/cases/conformance/jsx/file.tsx(13,71): error TS2322: Type 'string' is not assignable to type '{ x: string; }'.
tests/cases/conformance/jsx/file.tsx(13,54): error TS2322: Type '(a: { x: string; }) => string' is not assignable to type '((a: { x: string; }) => string) & ((cur: { x: string; }) => { x: string; })'.
Type '(a: { x: string; }) => string' is not assignable to type '(cur: { x: string; }) => { x: string; }'.
Type 'string' is not assignable to type '{ x: string; }'.
==== tests/cases/conformance/jsx/file.tsx (1 errors) ====
@@ -15,6 +17,8 @@ tests/cases/conformance/jsx/file.tsx(13,71): error TS2322: Type 'string' is not
let b = <GenericComponent initialValues={12} nextValues={a => a} />; // No error - Values should be reinstantiated with `number` (since `object` is a default, not a constraint)
let c = <GenericComponent initialValues={{ x: "y" }} nextValues={a => ({ x: a.x })} />; // No Error
let d = <GenericComponent initialValues={{ x: "y" }} nextValues={a => a.x} />; // Error - `string` is not assignable to `{x: string}`
~~~
!!! error TS2322: Type 'string' is not assignable to type '{ x: string; }'.
!!! related TS6502 tests/cases/conformance/jsx/file.tsx:4:15: The expected type comes from the return type of this signature.
~~~~~~~~~~
!!! error TS2322: Type '(a: { x: string; }) => string' is not assignable to type '((a: { x: string; }) => string) & ((cur: { x: string; }) => { x: string; })'.
!!! error TS2322: Type '(a: { x: string; }) => string' is not assignable to type '(cur: { x: string; }) => { x: string; }'.
!!! error TS2322: Type 'string' is not assignable to type '{ x: string; }'.
!!! related TS6500 tests/cases/conformance/jsx/file.tsx:13:54: The expected type comes from property 'nextValues' which is declared here on type 'IntrinsicAttributes & IntrinsicClassAttributes<GenericComponent<{ initialValues: { x: string; }; nextValues: (a: { x: string; }) => string; }, { x: string; }>> & { initialValues: { x: string; }; nextValues: (a: { x: string; }) => string; } & BaseProps<{ x: string; }> & { children?: ReactNode; }'

View File

@@ -0,0 +1,95 @@
//// [checkJsxSubtleSkipContextSensitiveBug.tsx]
/// <reference path="/.lib/react16.d.ts" />
import * as React from "react";
interface ErrorResult { error: true }
interface AsyncLoaderProps<TResult> {
readonly prop1: () => Promise<TResult>;
readonly prop2: (result: Exclude<TResult, ErrorResult>) => any;
}
class AsyncLoader<TResult> extends React.Component<AsyncLoaderProps<TResult>> {
render() { return null; }
}
async function load(): Promise<{ success: true } | ErrorResult> {
return { success: true };
}
const loader = <AsyncLoader
prop1={load}
prop2={result => result}
/>;
//// [checkJsxSubtleSkipContextSensitiveBug.js]
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
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 extendStatics(d, b);
};
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
exports.__esModule = true;
/// <reference path="react16.d.ts" />
var React = require("react");
var AsyncLoader = /** @class */ (function (_super) {
__extends(AsyncLoader, _super);
function AsyncLoader() {
return _super !== null && _super.apply(this, arguments) || this;
}
AsyncLoader.prototype.render = function () { return null; };
return AsyncLoader;
}(React.Component));
function load() {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2 /*return*/, { success: true }];
});
});
}
var loader = React.createElement(AsyncLoader, { prop1: load, prop2: function (result) { return result; } });

View File

@@ -0,0 +1,64 @@
=== tests/cases/conformance/jsx/checkJsxSubtleSkipContextSensitiveBug.tsx ===
/// <reference path="react16.d.ts" />
import * as React from "react";
>React : Symbol(React, Decl(checkJsxSubtleSkipContextSensitiveBug.tsx, 1, 6))
interface ErrorResult { error: true }
>ErrorResult : Symbol(ErrorResult, Decl(checkJsxSubtleSkipContextSensitiveBug.tsx, 1, 31))
>error : Symbol(ErrorResult.error, Decl(checkJsxSubtleSkipContextSensitiveBug.tsx, 3, 23))
interface AsyncLoaderProps<TResult> {
>AsyncLoaderProps : Symbol(AsyncLoaderProps, Decl(checkJsxSubtleSkipContextSensitiveBug.tsx, 3, 37))
>TResult : Symbol(TResult, Decl(checkJsxSubtleSkipContextSensitiveBug.tsx, 5, 27))
readonly prop1: () => Promise<TResult>;
>prop1 : Symbol(AsyncLoaderProps.prop1, Decl(checkJsxSubtleSkipContextSensitiveBug.tsx, 5, 37))
>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
>TResult : Symbol(TResult, Decl(checkJsxSubtleSkipContextSensitiveBug.tsx, 5, 27))
readonly prop2: (result: Exclude<TResult, ErrorResult>) => any;
>prop2 : Symbol(AsyncLoaderProps.prop2, Decl(checkJsxSubtleSkipContextSensitiveBug.tsx, 6, 43))
>result : Symbol(result, Decl(checkJsxSubtleSkipContextSensitiveBug.tsx, 8, 21))
>Exclude : Symbol(Exclude, Decl(lib.es5.d.ts, --, --))
>TResult : Symbol(TResult, Decl(checkJsxSubtleSkipContextSensitiveBug.tsx, 5, 27))
>ErrorResult : Symbol(ErrorResult, Decl(checkJsxSubtleSkipContextSensitiveBug.tsx, 1, 31))
}
class AsyncLoader<TResult> extends React.Component<AsyncLoaderProps<TResult>> {
>AsyncLoader : Symbol(AsyncLoader, Decl(checkJsxSubtleSkipContextSensitiveBug.tsx, 9, 1))
>TResult : Symbol(TResult, Decl(checkJsxSubtleSkipContextSensitiveBug.tsx, 11, 18))
>React.Component : Symbol(React.Component, Decl(react16.d.ts, 345, 54), Decl(react16.d.ts, 349, 94))
>React : Symbol(React, Decl(checkJsxSubtleSkipContextSensitiveBug.tsx, 1, 6))
>Component : Symbol(React.Component, Decl(react16.d.ts, 345, 54), Decl(react16.d.ts, 349, 94))
>AsyncLoaderProps : Symbol(AsyncLoaderProps, Decl(checkJsxSubtleSkipContextSensitiveBug.tsx, 3, 37))
>TResult : Symbol(TResult, Decl(checkJsxSubtleSkipContextSensitiveBug.tsx, 11, 18))
render() { return null; }
>render : Symbol(AsyncLoader.render, Decl(checkJsxSubtleSkipContextSensitiveBug.tsx, 11, 79))
}
async function load(): Promise<{ success: true } | ErrorResult> {
>load : Symbol(load, Decl(checkJsxSubtleSkipContextSensitiveBug.tsx, 13, 1))
>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
>success : Symbol(success, Decl(checkJsxSubtleSkipContextSensitiveBug.tsx, 15, 32))
>ErrorResult : Symbol(ErrorResult, Decl(checkJsxSubtleSkipContextSensitiveBug.tsx, 1, 31))
return { success: true };
>success : Symbol(success, Decl(checkJsxSubtleSkipContextSensitiveBug.tsx, 16, 12))
}
const loader = <AsyncLoader
>loader : Symbol(loader, Decl(checkJsxSubtleSkipContextSensitiveBug.tsx, 19, 5))
>AsyncLoader : Symbol(AsyncLoader, Decl(checkJsxSubtleSkipContextSensitiveBug.tsx, 9, 1))
prop1={load}
>prop1 : Symbol(prop1, Decl(checkJsxSubtleSkipContextSensitiveBug.tsx, 19, 27))
>load : Symbol(load, Decl(checkJsxSubtleSkipContextSensitiveBug.tsx, 13, 1))
prop2={result => result}
>prop2 : Symbol(prop2, Decl(checkJsxSubtleSkipContextSensitiveBug.tsx, 20, 16))
>result : Symbol(result, Decl(checkJsxSubtleSkipContextSensitiveBug.tsx, 21, 11))
>result : Symbol(result, Decl(checkJsxSubtleSkipContextSensitiveBug.tsx, 21, 11))
/>;

View File

@@ -0,0 +1,57 @@
=== tests/cases/conformance/jsx/checkJsxSubtleSkipContextSensitiveBug.tsx ===
/// <reference path="react16.d.ts" />
import * as React from "react";
>React : typeof React
interface ErrorResult { error: true }
>error : true
>true : true
interface AsyncLoaderProps<TResult> {
readonly prop1: () => Promise<TResult>;
>prop1 : () => Promise<TResult>
readonly prop2: (result: Exclude<TResult, ErrorResult>) => any;
>prop2 : (result: Exclude<TResult, ErrorResult>) => any
>result : Exclude<TResult, ErrorResult>
}
class AsyncLoader<TResult> extends React.Component<AsyncLoaderProps<TResult>> {
>AsyncLoader : AsyncLoader<TResult>
>React.Component : React.Component<AsyncLoaderProps<TResult>, {}, any>
>React : typeof React
>Component : typeof React.Component
render() { return null; }
>render : () => null
>null : null
}
async function load(): Promise<{ success: true } | ErrorResult> {
>load : () => Promise<ErrorResult | { success: true; }>
>success : true
>true : true
return { success: true };
>{ success: true } : { success: true; }
>success : true
>true : true
}
const loader = <AsyncLoader
>loader : JSX.Element
><AsyncLoader prop1={load} prop2={result => result}/> : JSX.Element
>AsyncLoader : typeof AsyncLoader
prop1={load}
>prop1 : () => Promise<ErrorResult | { success: true; }>
>load : () => Promise<ErrorResult | { success: true; }>
prop2={result => result}
>prop2 : (result: { success: true; }) => { success: true; }
>result => result : (result: { success: true; }) => { success: true; }
>result : { success: true; }
>result : { success: true; }
/>;

View File

@@ -1,6 +1,6 @@
tests/cases/conformance/types/contextualTypes/jsxAttributes/file.tsx(27,13): error TS2322: Type '{ extra: true; onClick: (k: "left" | "right") => void; }' is not assignable to type 'IntrinsicAttributes & LinkProps'.
Property 'extra' does not exist on type 'IntrinsicAttributes & LinkProps'.
tests/cases/conformance/types/contextualTypes/jsxAttributes/file.tsx(28,13): error TS2322: Type '{ onClick: (k: "left" | "right") => void; extra: true; }' is not assignable to type 'IntrinsicAttributes & LinkProps'.
tests/cases/conformance/types/contextualTypes/jsxAttributes/file.tsx(28,13): error TS2322: Type '{ onClick: (k: any) => void; extra: true; }' is not assignable to type 'IntrinsicAttributes & LinkProps'.
Property 'onClick' does not exist on type 'IntrinsicAttributes & LinkProps'.
tests/cases/conformance/types/contextualTypes/jsxAttributes/file.tsx(29,13): error TS2322: Type '{ extra: true; goTo: "home"; }' is not assignable to type 'IntrinsicAttributes & LinkProps'.
Property 'extra' does not exist on type 'IntrinsicAttributes & LinkProps'.
@@ -45,7 +45,7 @@ tests/cases/conformance/types/contextualTypes/jsxAttributes/file.tsx(36,13): err
!!! error TS2322: Property 'extra' does not exist on type 'IntrinsicAttributes & LinkProps'.
const b2 = <MainButton onClick={(k)=>{console.log(k)}} extra />; // k has type "left" | "right"
~~~~~~~~~~
!!! error TS2322: Type '{ onClick: (k: "left" | "right") => void; extra: true; }' is not assignable to type 'IntrinsicAttributes & LinkProps'.
!!! error TS2322: Type '{ onClick: (k: any) => void; extra: true; }' is not assignable to type 'IntrinsicAttributes & LinkProps'.
!!! error TS2322: Property 'onClick' does not exist on type 'IntrinsicAttributes & LinkProps'.
const b3 = <MainButton {...{goTo:"home"}} extra />; // goTo has type"home" | "contact"
~~~~~~~~~~

View File

@@ -81,14 +81,14 @@ const b2 = <MainButton onClick={(k)=>{console.log(k)}} extra />; // k has type
>b2 : JSX.Element
><MainButton onClick={(k)=>{console.log(k)}} extra /> : JSX.Element
>MainButton : { (buttonProps: ButtonProps): JSX.Element; (linkProps: LinkProps): JSX.Element; }
>onClick : (k: "left" | "right") => void
>(k)=>{console.log(k)} : (k: "left" | "right") => void
>k : "left" | "right"
>onClick : (k: any) => void
>(k)=>{console.log(k)} : (k: any) => void
>k : any
>console.log(k) : void
>console.log : (message?: any, ...optionalParams: any[]) => void
>console : Console
>log : (message?: any, ...optionalParams: any[]) => void
>k : "left" | "right"
>k : any
>extra : true
const b3 = <MainButton {...{goTo:"home"}} extra />; // goTo has type"home" | "contact"

View File

@@ -40,7 +40,7 @@ tests/cases/compiler/reactDefaultPropsInferenceSuccess.tsx(64,37): error TS2322:
!!! error TS2322: Type '(value: string) => void' is not assignable to type '"a" | "b" | ((value: string) => boolean) | undefined'.
!!! error TS2322: Type '(value: string) => void' is not assignable to type '(value: string) => boolean'.
!!! error TS2322: Type 'void' is not assignable to type 'boolean'.
!!! related TS6500 tests/cases/compiler/reactDefaultPropsInferenceSuccess.tsx:6:3: The expected type comes from property 'when' which is declared here on type 'IntrinsicAttributes & IntrinsicClassAttributes<FieldFeedback<BaseProps>> & Pick<Readonly<{ children?: ReactNode; }> & Readonly<BaseProps>, "children" | "error"> & Partial<Pick<Readonly<{ children?: ReactNode; }> & Readonly<BaseProps>, "when">> & Partial<Pick<{ when: () => boolean; }, never>>'
!!! related TS6500 tests/cases/compiler/reactDefaultPropsInferenceSuccess.tsx:6:3: The expected type comes from property 'when' which is declared here on type 'IntrinsicAttributes & IntrinsicClassAttributes<FieldFeedback<Props>> & Pick<Readonly<{ children?: ReactNode; }> & Readonly<Props>, "children" | "error"> & Partial<Pick<Readonly<{ children?: ReactNode; }> & Readonly<Props>, "when">> & Partial<Pick<{ when: () => boolean; }, never>>'
class FieldFeedbackBeta<P extends Props = BaseProps> extends React.Component<P> {
static defaultProps: BaseProps = {
@@ -61,7 +61,7 @@ tests/cases/compiler/reactDefaultPropsInferenceSuccess.tsx(64,37): error TS2322:
!!! error TS2322: Type '(value: string) => void' is not assignable to type '"a" | "b" | ((value: string) => boolean) | undefined'.
!!! error TS2322: Type '(value: string) => void' is not assignable to type '(value: string) => boolean'.
!!! error TS2322: Type 'void' is not assignable to type 'boolean'.
!!! related TS6500 tests/cases/compiler/reactDefaultPropsInferenceSuccess.tsx:6:3: The expected type comes from property 'when' which is declared here on type 'IntrinsicAttributes & IntrinsicClassAttributes<FieldFeedbackBeta<BaseProps>> & Pick<Readonly<{ children?: ReactNode; }> & Readonly<BaseProps>, "children"> & Partial<Pick<Readonly<{ children?: ReactNode; }> & Readonly<BaseProps>, "when" | "error">> & Partial<Pick<BaseProps, never>>'
!!! related TS6500 tests/cases/compiler/reactDefaultPropsInferenceSuccess.tsx:6:3: The expected type comes from property 'when' which is declared here on type 'IntrinsicAttributes & IntrinsicClassAttributes<FieldFeedbackBeta<Props>> & Pick<Readonly<{ children?: ReactNode; }> & Readonly<Props>, "children"> & Partial<Pick<Readonly<{ children?: ReactNode; }> & Readonly<Props>, "when" | "error">> & Partial<Pick<BaseProps, never>>'
interface MyPropsProps extends Props {
when: (value: string) => boolean;

View File

@@ -1,4 +1,4 @@
tests/cases/conformance/jsx/file.tsx(48,13): error TS2322: Type '{ children: string; to: string; onClick: (e: MouseEvent<any>) => void; }' is not assignable to type 'IntrinsicAttributes & HyphenProps'.
tests/cases/conformance/jsx/file.tsx(48,13): error TS2322: Type '{ children: string; to: string; onClick: (e: any) => void; }' is not assignable to type 'IntrinsicAttributes & HyphenProps'.
Property 'to' does not exist on type 'IntrinsicAttributes & HyphenProps'.
tests/cases/conformance/jsx/file.tsx(54,51): error TS2322: Type 'number' is not assignable to type 'string'.
tests/cases/conformance/jsx/file.tsx(55,68): error TS2322: Type 'true' is not assignable to type 'string'.
@@ -55,7 +55,7 @@ tests/cases/conformance/jsx/file.tsx(56,24): error TS2322: Type 'true' is not as
// Error
const b0 = <MainButton to='/some/path' onClick={(e)=>{}}>GO</MainButton>; // extra property;
~~~~~~~~~~
!!! error TS2322: Type '{ children: string; to: string; onClick: (e: MouseEvent<any>) => void; }' is not assignable to type 'IntrinsicAttributes & HyphenProps'.
!!! error TS2322: Type '{ children: string; to: string; onClick: (e: any) => void; }' is not assignable to type 'IntrinsicAttributes & HyphenProps'.
!!! error TS2322: Property 'to' does not exist on type 'IntrinsicAttributes & HyphenProps'.
const b1 = <MainButton onClick={(e: any)=> {}} {...obj0}>Hello world</MainButton>; // extra property;
const b2 = <MainButton {...{to: "10000"}} {...obj2} />; // extra property

View File

@@ -113,9 +113,9 @@ const b0 = <MainButton to='/some/path' onClick={(e)=>{}}>GO</MainButton>; // ex
><MainButton to='/some/path' onClick={(e)=>{}}>GO</MainButton> : JSX.Element
>MainButton : { (buttonProps: ButtonProps): JSX.Element; (linkProps: LinkProps): JSX.Element; (hyphenProps: HyphenProps): JSX.Element; }
>to : string
>onClick : (e: React.MouseEvent<any>) => void
>(e)=>{} : (e: React.MouseEvent<any>) => void
>e : React.MouseEvent<any>
>onClick : (e: any) => void
>(e)=>{} : (e: any) => void
>e : any
>MainButton : { (buttonProps: ButtonProps): JSX.Element; (linkProps: LinkProps): JSX.Element; (hyphenProps: HyphenProps): JSX.Element; }
const b1 = <MainButton onClick={(e: any)=> {}} {...obj0}>Hello world</MainButton>; // extra property;

View File

@@ -0,0 +1,27 @@
// @strict: true
// @jsx: react
// @lib: es6
// @skipLibCheck: true
/// <reference path="/.lib/react16.d.ts" />
import * as React from "react";
interface ErrorResult { error: true }
interface AsyncLoaderProps<TResult> {
readonly prop1: () => Promise<TResult>;
readonly prop2: (result: Exclude<TResult, ErrorResult>) => any;
}
class AsyncLoader<TResult> extends React.Component<AsyncLoaderProps<TResult>> {
render() { return null; }
}
async function load(): Promise<{ success: true } | ErrorResult> {
return { success: true };
}
const loader = <AsyncLoader
prop1={load}
prop2={result => result}
/>;