diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 74545e366fd..678a3fc95c1 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -20042,6 +20042,12 @@ namespace ts { }); if (!contextualMapper) { inferTypes(context.inferences, getReturnTypeOfSignature(contextualSignature), getReturnTypeOfSignature(signature), InferencePriority.ReturnType); + const signaturePredicate = getTypePredicateOfSignature(signature); + const contextualPredicate = getTypePredicateOfSignature(sourceSignature); + if (signaturePredicate && contextualPredicate && signaturePredicate.kind === contextualPredicate.kind && + (signaturePredicate.kind === TypePredicateKind.This || signaturePredicate.parameterIndex === (contextualPredicate as IdentifierTypePredicate).parameterIndex)) { + inferTypes(context.inferences, contextualPredicate.type, signaturePredicate.type, InferencePriority.ReturnType); + } } return getSignatureInstantiation(signature, getInferredTypes(context), isInJSFile(contextualSignature.declaration)); } diff --git a/tests/baselines/reference/returnTypePredicateIsInstantiateInContextOfTarget.js b/tests/baselines/reference/returnTypePredicateIsInstantiateInContextOfTarget.js new file mode 100644 index 00000000000..8428f81bd05 --- /dev/null +++ b/tests/baselines/reference/returnTypePredicateIsInstantiateInContextOfTarget.js @@ -0,0 +1,49 @@ +//// [returnTypePredicateIsInstantiateInContextOfTarget.tsx] +/// +import * as React from "react"; +class TestComponent extends React.Component<{ isAny: (obj: any) => obj is T }> { + static defaultProps = { + isAny: TestComponent.isAny + } + + // Type guard is defined as a static class property + static isAny(obj: any): obj is T { + return true; + } +} + +const TestRender = () => ; + +//// [returnTypePredicateIsInstantiateInContextOfTarget.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 __()); + }; +})(); +exports.__esModule = true; +/// +var React = require("react"); +var TestComponent = /** @class */ (function (_super) { + __extends(TestComponent, _super); + function TestComponent() { + return _super !== null && _super.apply(this, arguments) || this; + } + // Type guard is defined as a static class property + TestComponent.isAny = function (obj) { + return true; + }; + TestComponent.defaultProps = { + isAny: TestComponent.isAny + }; + return TestComponent; +}(React.Component)); +var TestRender = function () { return React.createElement(TestComponent, null); }; diff --git a/tests/baselines/reference/returnTypePredicateIsInstantiateInContextOfTarget.symbols b/tests/baselines/reference/returnTypePredicateIsInstantiateInContextOfTarget.symbols new file mode 100644 index 00000000000..9c7558aa642 --- /dev/null +++ b/tests/baselines/reference/returnTypePredicateIsInstantiateInContextOfTarget.symbols @@ -0,0 +1,42 @@ +=== tests/cases/compiler/returnTypePredicateIsInstantiateInContextOfTarget.tsx === +/// +import * as React from "react"; +>React : Symbol(React, Decl(returnTypePredicateIsInstantiateInContextOfTarget.tsx, 1, 6)) + +class TestComponent extends React.Component<{ isAny: (obj: any) => obj is T }> { +>TestComponent : Symbol(TestComponent, Decl(returnTypePredicateIsInstantiateInContextOfTarget.tsx, 1, 31)) +>React.Component : Symbol(React.Component, Decl(react16.d.ts, 345, 54), Decl(react16.d.ts, 349, 94)) +>React : Symbol(React, Decl(returnTypePredicateIsInstantiateInContextOfTarget.tsx, 1, 6)) +>Component : Symbol(React.Component, Decl(react16.d.ts, 345, 54), Decl(react16.d.ts, 349, 94)) +>isAny : Symbol(isAny, Decl(returnTypePredicateIsInstantiateInContextOfTarget.tsx, 2, 45)) +>T : Symbol(T, Decl(returnTypePredicateIsInstantiateInContextOfTarget.tsx, 2, 54)) +>obj : Symbol(obj, Decl(returnTypePredicateIsInstantiateInContextOfTarget.tsx, 2, 57)) +>obj : Symbol(obj, Decl(returnTypePredicateIsInstantiateInContextOfTarget.tsx, 2, 57)) +>T : Symbol(T, Decl(returnTypePredicateIsInstantiateInContextOfTarget.tsx, 2, 54)) + + static defaultProps = { +>defaultProps : Symbol(TestComponent.defaultProps, Decl(returnTypePredicateIsInstantiateInContextOfTarget.tsx, 2, 83)) + + isAny: TestComponent.isAny +>isAny : Symbol(isAny, Decl(returnTypePredicateIsInstantiateInContextOfTarget.tsx, 3, 27)) +>TestComponent.isAny : Symbol(TestComponent.isAny, Decl(returnTypePredicateIsInstantiateInContextOfTarget.tsx, 5, 5)) +>TestComponent : Symbol(TestComponent, Decl(returnTypePredicateIsInstantiateInContextOfTarget.tsx, 1, 31)) +>isAny : Symbol(TestComponent.isAny, Decl(returnTypePredicateIsInstantiateInContextOfTarget.tsx, 5, 5)) + } + + // Type guard is defined as a static class property + static isAny(obj: any): obj is T { +>isAny : Symbol(TestComponent.isAny, Decl(returnTypePredicateIsInstantiateInContextOfTarget.tsx, 5, 5)) +>T : Symbol(T, Decl(returnTypePredicateIsInstantiateInContextOfTarget.tsx, 8, 17)) +>obj : Symbol(obj, Decl(returnTypePredicateIsInstantiateInContextOfTarget.tsx, 8, 20)) +>obj : Symbol(obj, Decl(returnTypePredicateIsInstantiateInContextOfTarget.tsx, 8, 20)) +>T : Symbol(T, Decl(returnTypePredicateIsInstantiateInContextOfTarget.tsx, 8, 17)) + + return true; + } +} + +const TestRender = () => ; +>TestRender : Symbol(TestRender, Decl(returnTypePredicateIsInstantiateInContextOfTarget.tsx, 13, 5)) +>TestComponent : Symbol(TestComponent, Decl(returnTypePredicateIsInstantiateInContextOfTarget.tsx, 1, 31)) + diff --git a/tests/baselines/reference/returnTypePredicateIsInstantiateInContextOfTarget.types b/tests/baselines/reference/returnTypePredicateIsInstantiateInContextOfTarget.types new file mode 100644 index 00000000000..4780b2722e5 --- /dev/null +++ b/tests/baselines/reference/returnTypePredicateIsInstantiateInContextOfTarget.types @@ -0,0 +1,40 @@ +=== tests/cases/compiler/returnTypePredicateIsInstantiateInContextOfTarget.tsx === +/// +import * as React from "react"; +>React : typeof React + +class TestComponent extends React.Component<{ isAny: (obj: any) => obj is T }> { +>TestComponent : TestComponent +>React.Component : React.Component<{ isAny: (obj: any) => obj is T; }, {}, any> +>React : typeof React +>Component : typeof React.Component +>isAny : (obj: any) => obj is T +>obj : any + + static defaultProps = { +>defaultProps : { isAny: (obj: any) => obj is T; } +>{ isAny: TestComponent.isAny } : { isAny: (obj: any) => obj is T; } + + isAny: TestComponent.isAny +>isAny : (obj: any) => obj is T +>TestComponent.isAny : (obj: any) => obj is T +>TestComponent : typeof TestComponent +>isAny : (obj: any) => obj is T + } + + // Type guard is defined as a static class property + static isAny(obj: any): obj is T { +>isAny : (obj: any) => obj is T +>obj : any + + return true; +>true : true + } +} + +const TestRender = () => ; +>TestRender : () => JSX.Element +>() => : () => JSX.Element +> : JSX.Element +>TestComponent : typeof TestComponent + diff --git a/tests/cases/compiler/returnTypePredicateIsInstantiateInContextOfTarget.tsx b/tests/cases/compiler/returnTypePredicateIsInstantiateInContextOfTarget.tsx new file mode 100644 index 00000000000..8a27e3fde7c --- /dev/null +++ b/tests/cases/compiler/returnTypePredicateIsInstantiateInContextOfTarget.tsx @@ -0,0 +1,16 @@ +// @jsx: react +// @strict: true +/// +import * as React from "react"; +class TestComponent extends React.Component<{ isAny: (obj: any) => obj is T }> { + static defaultProps = { + isAny: TestComponent.isAny + } + + // Type guard is defined as a static class property + static isAny(obj: any): obj is T { + return true; + } +} + +const TestRender = () => ; \ No newline at end of file