Skip to content

Commit e982240

Browse files
authored
Instantiating a signature in the context of another should infer from return type predicates if they match up (microsoft#30242)
* Instantiating a signature in the context of another should infer from return type predicates if they match up * Invert condition per PR feedback
1 parent 4c9ad08 commit e982240

5 files changed

+153
-0
lines changed

src/compiler/checker.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20042,6 +20042,12 @@ namespace ts {
2004220042
});
2004320043
if (!contextualMapper) {
2004420044
inferTypes(context.inferences, getReturnTypeOfSignature(contextualSignature), getReturnTypeOfSignature(signature), InferencePriority.ReturnType);
20045+
const signaturePredicate = getTypePredicateOfSignature(signature);
20046+
const contextualPredicate = getTypePredicateOfSignature(sourceSignature);
20047+
if (signaturePredicate && contextualPredicate && signaturePredicate.kind === contextualPredicate.kind &&
20048+
(signaturePredicate.kind === TypePredicateKind.This || signaturePredicate.parameterIndex === (contextualPredicate as IdentifierTypePredicate).parameterIndex)) {
20049+
inferTypes(context.inferences, contextualPredicate.type, signaturePredicate.type, InferencePriority.ReturnType);
20050+
}
2004520051
}
2004620052
return getSignatureInstantiation(signature, getInferredTypes(context), isInJSFile(contextualSignature.declaration));
2004720053
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
//// [returnTypePredicateIsInstantiateInContextOfTarget.tsx]
2+
/// <reference path="/.lib/react16.d.ts" />
3+
import * as React from "react";
4+
class TestComponent extends React.Component<{ isAny: <T>(obj: any) => obj is T }> {
5+
static defaultProps = {
6+
isAny: TestComponent.isAny
7+
}
8+
9+
// Type guard is defined as a static class property
10+
static isAny<T>(obj: any): obj is T {
11+
return true;
12+
}
13+
}
14+
15+
const TestRender = () => <TestComponent />;
16+
17+
//// [returnTypePredicateIsInstantiateInContextOfTarget.js]
18+
"use strict";
19+
var __extends = (this && this.__extends) || (function () {
20+
var extendStatics = function (d, b) {
21+
extendStatics = Object.setPrototypeOf ||
22+
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
23+
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
24+
return extendStatics(d, b);
25+
};
26+
return function (d, b) {
27+
extendStatics(d, b);
28+
function __() { this.constructor = d; }
29+
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
30+
};
31+
})();
32+
exports.__esModule = true;
33+
/// <reference path="react16.d.ts" />
34+
var React = require("react");
35+
var TestComponent = /** @class */ (function (_super) {
36+
__extends(TestComponent, _super);
37+
function TestComponent() {
38+
return _super !== null && _super.apply(this, arguments) || this;
39+
}
40+
// Type guard is defined as a static class property
41+
TestComponent.isAny = function (obj) {
42+
return true;
43+
};
44+
TestComponent.defaultProps = {
45+
isAny: TestComponent.isAny
46+
};
47+
return TestComponent;
48+
}(React.Component));
49+
var TestRender = function () { return React.createElement(TestComponent, null); };
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
=== tests/cases/compiler/returnTypePredicateIsInstantiateInContextOfTarget.tsx ===
2+
/// <reference path="react16.d.ts" />
3+
import * as React from "react";
4+
>React : Symbol(React, Decl(returnTypePredicateIsInstantiateInContextOfTarget.tsx, 1, 6))
5+
6+
class TestComponent extends React.Component<{ isAny: <T>(obj: any) => obj is T }> {
7+
>TestComponent : Symbol(TestComponent, Decl(returnTypePredicateIsInstantiateInContextOfTarget.tsx, 1, 31))
8+
>React.Component : Symbol(React.Component, Decl(react16.d.ts, 345, 54), Decl(react16.d.ts, 349, 94))
9+
>React : Symbol(React, Decl(returnTypePredicateIsInstantiateInContextOfTarget.tsx, 1, 6))
10+
>Component : Symbol(React.Component, Decl(react16.d.ts, 345, 54), Decl(react16.d.ts, 349, 94))
11+
>isAny : Symbol(isAny, Decl(returnTypePredicateIsInstantiateInContextOfTarget.tsx, 2, 45))
12+
>T : Symbol(T, Decl(returnTypePredicateIsInstantiateInContextOfTarget.tsx, 2, 54))
13+
>obj : Symbol(obj, Decl(returnTypePredicateIsInstantiateInContextOfTarget.tsx, 2, 57))
14+
>obj : Symbol(obj, Decl(returnTypePredicateIsInstantiateInContextOfTarget.tsx, 2, 57))
15+
>T : Symbol(T, Decl(returnTypePredicateIsInstantiateInContextOfTarget.tsx, 2, 54))
16+
17+
static defaultProps = {
18+
>defaultProps : Symbol(TestComponent.defaultProps, Decl(returnTypePredicateIsInstantiateInContextOfTarget.tsx, 2, 83))
19+
20+
isAny: TestComponent.isAny
21+
>isAny : Symbol(isAny, Decl(returnTypePredicateIsInstantiateInContextOfTarget.tsx, 3, 27))
22+
>TestComponent.isAny : Symbol(TestComponent.isAny, Decl(returnTypePredicateIsInstantiateInContextOfTarget.tsx, 5, 5))
23+
>TestComponent : Symbol(TestComponent, Decl(returnTypePredicateIsInstantiateInContextOfTarget.tsx, 1, 31))
24+
>isAny : Symbol(TestComponent.isAny, Decl(returnTypePredicateIsInstantiateInContextOfTarget.tsx, 5, 5))
25+
}
26+
27+
// Type guard is defined as a static class property
28+
static isAny<T>(obj: any): obj is T {
29+
>isAny : Symbol(TestComponent.isAny, Decl(returnTypePredicateIsInstantiateInContextOfTarget.tsx, 5, 5))
30+
>T : Symbol(T, Decl(returnTypePredicateIsInstantiateInContextOfTarget.tsx, 8, 17))
31+
>obj : Symbol(obj, Decl(returnTypePredicateIsInstantiateInContextOfTarget.tsx, 8, 20))
32+
>obj : Symbol(obj, Decl(returnTypePredicateIsInstantiateInContextOfTarget.tsx, 8, 20))
33+
>T : Symbol(T, Decl(returnTypePredicateIsInstantiateInContextOfTarget.tsx, 8, 17))
34+
35+
return true;
36+
}
37+
}
38+
39+
const TestRender = () => <TestComponent />;
40+
>TestRender : Symbol(TestRender, Decl(returnTypePredicateIsInstantiateInContextOfTarget.tsx, 13, 5))
41+
>TestComponent : Symbol(TestComponent, Decl(returnTypePredicateIsInstantiateInContextOfTarget.tsx, 1, 31))
42+
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
=== tests/cases/compiler/returnTypePredicateIsInstantiateInContextOfTarget.tsx ===
2+
/// <reference path="react16.d.ts" />
3+
import * as React from "react";
4+
>React : typeof React
5+
6+
class TestComponent extends React.Component<{ isAny: <T>(obj: any) => obj is T }> {
7+
>TestComponent : TestComponent
8+
>React.Component : React.Component<{ isAny: <T>(obj: any) => obj is T; }, {}, any>
9+
>React : typeof React
10+
>Component : typeof React.Component
11+
>isAny : <T>(obj: any) => obj is T
12+
>obj : any
13+
14+
static defaultProps = {
15+
>defaultProps : { isAny: <T>(obj: any) => obj is T; }
16+
>{ isAny: TestComponent.isAny } : { isAny: <T>(obj: any) => obj is T; }
17+
18+
isAny: TestComponent.isAny
19+
>isAny : <T>(obj: any) => obj is T
20+
>TestComponent.isAny : <T>(obj: any) => obj is T
21+
>TestComponent : typeof TestComponent
22+
>isAny : <T>(obj: any) => obj is T
23+
}
24+
25+
// Type guard is defined as a static class property
26+
static isAny<T>(obj: any): obj is T {
27+
>isAny : <T>(obj: any) => obj is T
28+
>obj : any
29+
30+
return true;
31+
>true : true
32+
}
33+
}
34+
35+
const TestRender = () => <TestComponent />;
36+
>TestRender : () => JSX.Element
37+
>() => <TestComponent /> : () => JSX.Element
38+
><TestComponent /> : JSX.Element
39+
>TestComponent : typeof TestComponent
40+
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// @jsx: react
2+
// @strict: true
3+
/// <reference path="/.lib/react16.d.ts" />
4+
import * as React from "react";
5+
class TestComponent extends React.Component<{ isAny: <T>(obj: any) => obj is T }> {
6+
static defaultProps = {
7+
isAny: TestComponent.isAny
8+
}
9+
10+
// Type guard is defined as a static class property
11+
static isAny<T>(obj: any): obj is T {
12+
return true;
13+
}
14+
}
15+
16+
const TestRender = () => <TestComponent />;

0 commit comments

Comments
 (0)