Skip to content

Commit 6da73b0

Browse files
authored
Port #17771 to release-2.5 (#18018)
* No contextual return type when type is circular * Add regression test
1 parent 1420fbc commit 6da73b0

File tree

5 files changed

+74
-1
lines changed

5 files changed

+74
-1
lines changed

src/compiler/checker.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6584,6 +6584,10 @@ namespace ts {
65846584
return signature.resolvedReturnType;
65856585
}
65866586

6587+
function isResolvingReturnTypeOfSignature(signature: Signature) {
6588+
return !signature.resolvedReturnType && findResolutionCycleStartIndex(signature, TypeSystemPropertyName.ResolvedReturnType) >= 0;
6589+
}
6590+
65876591
function getRestTypeOfSignature(signature: Signature): Type {
65886592
if (signature.hasRestParameter) {
65896593
const type = getTypeOfSymbol(lastOrUndefined(signature.parameters));
@@ -12957,7 +12961,7 @@ namespace ts {
1295712961
// Otherwise, if the containing function is contextually typed by a function type with exactly one call signature
1295812962
// and that call signature is non-generic, return statements are contextually typed by the return type of the signature
1295912963
const signature = getContextualSignatureForFunctionLikeDeclaration(<FunctionExpression>functionDecl);
12960-
if (signature) {
12964+
if (signature && !isResolvingReturnTypeOfSignature(signature)) {
1296112965
return getReturnTypeOfSignature(signature);
1296212966
}
1296312967

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//// [circularContextualReturnType.ts]
2+
// Repro from #17711
3+
4+
Object.freeze({
5+
foo() {
6+
return Object.freeze('a');
7+
},
8+
});
9+
10+
11+
//// [circularContextualReturnType.js]
12+
"use strict";
13+
// Repro from #17711
14+
Object.freeze({
15+
foo: function () {
16+
return Object.freeze('a');
17+
}
18+
});
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
=== tests/cases/compiler/circularContextualReturnType.ts ===
2+
// Repro from #17711
3+
4+
Object.freeze({
5+
>Object.freeze : Symbol(ObjectConstructor.freeze, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
6+
>Object : Symbol(Object, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
7+
>freeze : Symbol(ObjectConstructor.freeze, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
8+
9+
foo() {
10+
>foo : Symbol(foo, Decl(circularContextualReturnType.ts, 2, 15))
11+
12+
return Object.freeze('a');
13+
>Object.freeze : Symbol(ObjectConstructor.freeze, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
14+
>Object : Symbol(Object, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
15+
>freeze : Symbol(ObjectConstructor.freeze, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
16+
17+
},
18+
});
19+
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
=== tests/cases/compiler/circularContextualReturnType.ts ===
2+
// Repro from #17711
3+
4+
Object.freeze({
5+
>Object.freeze({ foo() { return Object.freeze('a'); },}) : Readonly<{ foo(): string; }>
6+
>Object.freeze : { <T>(a: T[]): ReadonlyArray<T>; <T extends Function>(f: T): T; <T>(o: T): Readonly<T>; }
7+
>Object : ObjectConstructor
8+
>freeze : { <T>(a: T[]): ReadonlyArray<T>; <T extends Function>(f: T): T; <T>(o: T): Readonly<T>; }
9+
>{ foo() { return Object.freeze('a'); },} : { foo(): string; }
10+
11+
foo() {
12+
>foo : () => string
13+
14+
return Object.freeze('a');
15+
>Object.freeze('a') : string
16+
>Object.freeze : { <T>(a: T[]): ReadonlyArray<T>; <T extends Function>(f: T): T; <T>(o: T): Readonly<T>; }
17+
>Object : ObjectConstructor
18+
>freeze : { <T>(a: T[]): ReadonlyArray<T>; <T extends Function>(f: T): T; <T>(o: T): Readonly<T>; }
19+
>'a' : "a"
20+
21+
},
22+
});
23+
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// @strict: true
2+
3+
// Repro from #17711
4+
5+
Object.freeze({
6+
foo() {
7+
return Object.freeze('a');
8+
},
9+
});

0 commit comments

Comments
 (0)