Skip to content

Commit a72e49e

Browse files
authored
Delay pulling on signature contextual type until absolutely needed (#37851)
1 parent 136f728 commit a72e49e

6 files changed

+131
-8
lines changed

src/compiler/checker.ts

+8-8
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,9 @@ namespace ts {
5555

5656
const enum WideningKind {
5757
Normal,
58-
GeneratorYield
58+
FunctionReturn,
59+
GeneratorNext,
60+
GeneratorYield,
5961
}
6062

6163
const enum TypeFacts {
@@ -18092,7 +18094,7 @@ namespace ts {
1809218094
}
1809318095

1809418096
function reportErrorsFromWidening(declaration: Declaration, type: Type, wideningKind?: WideningKind) {
18095-
if (produceDiagnostics && noImplicitAny && getObjectFlags(type) & ObjectFlags.ContainsWideningType) {
18097+
if (produceDiagnostics && noImplicitAny && getObjectFlags(type) & ObjectFlags.ContainsWideningType && (!wideningKind || !getContextualSignatureForFunctionLikeDeclaration(declaration as FunctionLikeDeclaration))) {
1809618098
// Report implicit any error within type if possible, otherwise report error on declaration
1809718099
if (!reportWideningErrorsInType(type)) {
1809818100
reportImplicitAny(declaration, type, wideningKind);
@@ -27047,15 +27049,13 @@ namespace ts {
2704727049
}
2704827050

2704927051
if (returnType || yieldType || nextType) {
27050-
const contextualSignature = getContextualSignatureForFunctionLikeDeclaration(func);
27051-
if (!contextualSignature) {
27052-
if (yieldType) reportErrorsFromWidening(func, yieldType, WideningKind.GeneratorYield);
27053-
if (returnType) reportErrorsFromWidening(func, returnType);
27054-
if (nextType) reportErrorsFromWidening(func, nextType);
27055-
}
27052+
if (yieldType) reportErrorsFromWidening(func, yieldType, WideningKind.GeneratorYield);
27053+
if (returnType) reportErrorsFromWidening(func, returnType, WideningKind.FunctionReturn);
27054+
if (nextType) reportErrorsFromWidening(func, nextType, WideningKind.GeneratorNext);
2705627055
if (returnType && isUnitType(returnType) ||
2705727056
yieldType && isUnitType(yieldType) ||
2705827057
nextType && isUnitType(nextType)) {
27058+
const contextualSignature = getContextualSignatureForFunctionLikeDeclaration(func);
2705927059
const contextualType = !contextualSignature ? undefined :
2706027060
contextualSignature === getSignatureFromDeclaration(func) ? isGenerator ? undefined : returnType :
2706127061
instantiateContextualType(getReturnTypeOfSignature(contextualSignature), func);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
tests/cases/compiler/reverseMappedTypeContextualTypeNotCircular.ts(10,3): error TS2322: Type '(state: any, props: any) => {}' is not assignable to type 'Selector<unknown, {}>'.
2+
3+
4+
==== tests/cases/compiler/reverseMappedTypeContextualTypeNotCircular.ts (1 errors) ====
5+
type Selector<S, R> = (state: S) => R;
6+
7+
declare function createStructuredSelector<S, T>(
8+
selectors: {[K in keyof T]: Selector<S, T[K]>},
9+
): Selector<S, T>;
10+
11+
const editable = () => ({});
12+
13+
const mapStateToProps = createStructuredSelector({
14+
editable: (state: any, props: any) => editable(), // expect "Type '(state: any, props: any) => {}' is not assignable to type 'Selector<unknown, {}>'", _not_ a circularity error
15+
~~~~~~~~
16+
!!! error TS2322: Type '(state: any, props: any) => {}' is not assignable to type 'Selector<unknown, {}>'.
17+
!!! related TS6500 tests/cases/compiler/reverseMappedTypeContextualTypeNotCircular.ts:10:3: The expected type comes from property 'editable' which is declared here on type '{ editable: Selector<unknown, {}>; }'
18+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//// [reverseMappedTypeContextualTypeNotCircular.ts]
2+
type Selector<S, R> = (state: S) => R;
3+
4+
declare function createStructuredSelector<S, T>(
5+
selectors: {[K in keyof T]: Selector<S, T[K]>},
6+
): Selector<S, T>;
7+
8+
const editable = () => ({});
9+
10+
const mapStateToProps = createStructuredSelector({
11+
editable: (state: any, props: any) => editable(), // expect "Type '(state: any, props: any) => {}' is not assignable to type 'Selector<unknown, {}>'", _not_ a circularity error
12+
});
13+
14+
//// [reverseMappedTypeContextualTypeNotCircular.js]
15+
var editable = function () { return ({}); };
16+
var mapStateToProps = createStructuredSelector({
17+
editable: function (state, props) { return editable(); }
18+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
=== tests/cases/compiler/reverseMappedTypeContextualTypeNotCircular.ts ===
2+
type Selector<S, R> = (state: S) => R;
3+
>Selector : Symbol(Selector, Decl(reverseMappedTypeContextualTypeNotCircular.ts, 0, 0))
4+
>S : Symbol(S, Decl(reverseMappedTypeContextualTypeNotCircular.ts, 0, 14))
5+
>R : Symbol(R, Decl(reverseMappedTypeContextualTypeNotCircular.ts, 0, 16))
6+
>state : Symbol(state, Decl(reverseMappedTypeContextualTypeNotCircular.ts, 0, 23))
7+
>S : Symbol(S, Decl(reverseMappedTypeContextualTypeNotCircular.ts, 0, 14))
8+
>R : Symbol(R, Decl(reverseMappedTypeContextualTypeNotCircular.ts, 0, 16))
9+
10+
declare function createStructuredSelector<S, T>(
11+
>createStructuredSelector : Symbol(createStructuredSelector, Decl(reverseMappedTypeContextualTypeNotCircular.ts, 0, 38))
12+
>S : Symbol(S, Decl(reverseMappedTypeContextualTypeNotCircular.ts, 2, 42))
13+
>T : Symbol(T, Decl(reverseMappedTypeContextualTypeNotCircular.ts, 2, 44))
14+
15+
selectors: {[K in keyof T]: Selector<S, T[K]>},
16+
>selectors : Symbol(selectors, Decl(reverseMappedTypeContextualTypeNotCircular.ts, 2, 48))
17+
>K : Symbol(K, Decl(reverseMappedTypeContextualTypeNotCircular.ts, 3, 15))
18+
>T : Symbol(T, Decl(reverseMappedTypeContextualTypeNotCircular.ts, 2, 44))
19+
>Selector : Symbol(Selector, Decl(reverseMappedTypeContextualTypeNotCircular.ts, 0, 0))
20+
>S : Symbol(S, Decl(reverseMappedTypeContextualTypeNotCircular.ts, 2, 42))
21+
>T : Symbol(T, Decl(reverseMappedTypeContextualTypeNotCircular.ts, 2, 44))
22+
>K : Symbol(K, Decl(reverseMappedTypeContextualTypeNotCircular.ts, 3, 15))
23+
24+
): Selector<S, T>;
25+
>Selector : Symbol(Selector, Decl(reverseMappedTypeContextualTypeNotCircular.ts, 0, 0))
26+
>S : Symbol(S, Decl(reverseMappedTypeContextualTypeNotCircular.ts, 2, 42))
27+
>T : Symbol(T, Decl(reverseMappedTypeContextualTypeNotCircular.ts, 2, 44))
28+
29+
const editable = () => ({});
30+
>editable : Symbol(editable, Decl(reverseMappedTypeContextualTypeNotCircular.ts, 6, 5))
31+
32+
const mapStateToProps = createStructuredSelector({
33+
>mapStateToProps : Symbol(mapStateToProps, Decl(reverseMappedTypeContextualTypeNotCircular.ts, 8, 5))
34+
>createStructuredSelector : Symbol(createStructuredSelector, Decl(reverseMappedTypeContextualTypeNotCircular.ts, 0, 38))
35+
36+
editable: (state: any, props: any) => editable(), // expect "Type '(state: any, props: any) => {}' is not assignable to type 'Selector<unknown, {}>'", _not_ a circularity error
37+
>editable : Symbol(editable, Decl(reverseMappedTypeContextualTypeNotCircular.ts, 8, 50))
38+
>state : Symbol(state, Decl(reverseMappedTypeContextualTypeNotCircular.ts, 9, 13))
39+
>props : Symbol(props, Decl(reverseMappedTypeContextualTypeNotCircular.ts, 9, 24))
40+
>editable : Symbol(editable, Decl(reverseMappedTypeContextualTypeNotCircular.ts, 6, 5))
41+
42+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
=== tests/cases/compiler/reverseMappedTypeContextualTypeNotCircular.ts ===
2+
type Selector<S, R> = (state: S) => R;
3+
>Selector : Selector<S, R>
4+
>state : S
5+
6+
declare function createStructuredSelector<S, T>(
7+
>createStructuredSelector : <S, T>(selectors: { [K in keyof T]: Selector<S, T[K]>; }) => Selector<S, T>
8+
9+
selectors: {[K in keyof T]: Selector<S, T[K]>},
10+
>selectors : { [K in keyof T]: Selector<S, T[K]>; }
11+
12+
): Selector<S, T>;
13+
14+
const editable = () => ({});
15+
>editable : () => {}
16+
>() => ({}) : () => {}
17+
>({}) : {}
18+
>{} : {}
19+
20+
const mapStateToProps = createStructuredSelector({
21+
>mapStateToProps : Selector<unknown, { editable: {}; }>
22+
>createStructuredSelector({ editable: (state: any, props: any) => editable(), // expect "Type '(state: any, props: any) => {}' is not assignable to type 'Selector<unknown, {}>'", _not_ a circularity error}) : Selector<unknown, { editable: {}; }>
23+
>createStructuredSelector : <S, T>(selectors: { [K in keyof T]: Selector<S, T[K]>; }) => Selector<S, T>
24+
>{ editable: (state: any, props: any) => editable(), // expect "Type '(state: any, props: any) => {}' is not assignable to type 'Selector<unknown, {}>'", _not_ a circularity error} : { editable: (state: any, props: any) => {}; }
25+
26+
editable: (state: any, props: any) => editable(), // expect "Type '(state: any, props: any) => {}' is not assignable to type 'Selector<unknown, {}>'", _not_ a circularity error
27+
>editable : (state: any, props: any) => {}
28+
>(state: any, props: any) => editable() : (state: any, props: any) => {}
29+
>state : any
30+
>props : any
31+
>editable() : {}
32+
>editable : () => {}
33+
34+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
type Selector<S, R> = (state: S) => R;
2+
3+
declare function createStructuredSelector<S, T>(
4+
selectors: {[K in keyof T]: Selector<S, T[K]>},
5+
): Selector<S, T>;
6+
7+
const editable = () => ({});
8+
9+
const mapStateToProps = createStructuredSelector({
10+
editable: (state: any, props: any) => editable(), // expect "Type '(state: any, props: any) => {}' is not assignable to type 'Selector<unknown, {}>'", _not_ a circularity error
11+
});

0 commit comments

Comments
 (0)