diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 07c94bd746e0f..1ba33f8c82bd6 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6576,6 +6576,10 @@ namespace ts { return signature.resolvedReturnType; } + function isResolvingReturnTypeOfSignature(signature: Signature) { + return !signature.resolvedReturnType && findResolutionCycleStartIndex(signature, TypeSystemPropertyName.ResolvedReturnType) >= 0; + } + function getRestTypeOfSignature(signature: Signature): Type { if (signature.hasRestParameter) { const type = getTypeOfSymbol(lastOrUndefined(signature.parameters)); @@ -12949,7 +12953,7 @@ namespace ts { // Otherwise, if the containing function is contextually typed by a function type with exactly one call signature // and that call signature is non-generic, return statements are contextually typed by the return type of the signature const signature = getContextualSignatureForFunctionLikeDeclaration(functionDecl); - if (signature) { + if (signature && !isResolvingReturnTypeOfSignature(signature)) { return getReturnTypeOfSignature(signature); } diff --git a/tests/baselines/reference/circularContextualReturnType.js b/tests/baselines/reference/circularContextualReturnType.js new file mode 100644 index 0000000000000..d68f25494a89c --- /dev/null +++ b/tests/baselines/reference/circularContextualReturnType.js @@ -0,0 +1,18 @@ +//// [circularContextualReturnType.ts] +// Repro from #17711 + +Object.freeze({ + foo() { + return Object.freeze('a'); + }, +}); + + +//// [circularContextualReturnType.js] +"use strict"; +// Repro from #17711 +Object.freeze({ + foo: function () { + return Object.freeze('a'); + } +}); diff --git a/tests/baselines/reference/circularContextualReturnType.symbols b/tests/baselines/reference/circularContextualReturnType.symbols new file mode 100644 index 0000000000000..d0e81a6b33d35 --- /dev/null +++ b/tests/baselines/reference/circularContextualReturnType.symbols @@ -0,0 +1,19 @@ +=== tests/cases/compiler/circularContextualReturnType.ts === +// Repro from #17711 + +Object.freeze({ +>Object.freeze : Symbol(ObjectConstructor.freeze, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>Object : Symbol(Object, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>freeze : Symbol(ObjectConstructor.freeze, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) + + foo() { +>foo : Symbol(foo, Decl(circularContextualReturnType.ts, 2, 15)) + + return Object.freeze('a'); +>Object.freeze : Symbol(ObjectConstructor.freeze, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>Object : Symbol(Object, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>freeze : Symbol(ObjectConstructor.freeze, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) + + }, +}); + diff --git a/tests/baselines/reference/circularContextualReturnType.types b/tests/baselines/reference/circularContextualReturnType.types new file mode 100644 index 0000000000000..d32640d2cd970 --- /dev/null +++ b/tests/baselines/reference/circularContextualReturnType.types @@ -0,0 +1,23 @@ +=== tests/cases/compiler/circularContextualReturnType.ts === +// Repro from #17711 + +Object.freeze({ +>Object.freeze({ foo() { return Object.freeze('a'); },}) : Readonly<{ foo(): string; }> +>Object.freeze : { (a: T[]): ReadonlyArray; (f: T): T; (o: T): Readonly; } +>Object : ObjectConstructor +>freeze : { (a: T[]): ReadonlyArray; (f: T): T; (o: T): Readonly; } +>{ foo() { return Object.freeze('a'); },} : { foo(): string; } + + foo() { +>foo : () => string + + return Object.freeze('a'); +>Object.freeze('a') : string +>Object.freeze : { (a: T[]): ReadonlyArray; (f: T): T; (o: T): Readonly; } +>Object : ObjectConstructor +>freeze : { (a: T[]): ReadonlyArray; (f: T): T; (o: T): Readonly; } +>'a' : "a" + + }, +}); + diff --git a/tests/cases/compiler/circularContextualReturnType.ts b/tests/cases/compiler/circularContextualReturnType.ts new file mode 100644 index 0000000000000..1b356aff160de --- /dev/null +++ b/tests/cases/compiler/circularContextualReturnType.ts @@ -0,0 +1,9 @@ +// @strict: true + +// Repro from #17711 + +Object.freeze({ + foo() { + return Object.freeze('a'); + }, +});