Fixed a crash caused by circularly-reentrant getEffectsSignature (#63026)

This commit is contained in:
Mateusz Burzyński 2026-02-02 19:44:59 +01:00 committed by GitHub
parent 8a55156f23
commit b92ec99cac
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 1387 additions and 4 deletions

View File

@ -488,6 +488,7 @@ export const enum ContainerFlags {
HasLocals = 1 << 5,
IsInterface = 1 << 6,
IsObjectLiteralOrClassExpressionMethodOrAccessor = 1 << 7,
PropagatesThisKeyword = 1 << 8,
}
/** @internal */
@ -1055,7 +1056,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
currentExceptionTarget = saveExceptionTarget;
activeLabelList = saveActiveLabelList;
hasExplicitReturn = saveHasExplicitReturn;
seenThisKeyword = node.kind === SyntaxKind.ArrowFunction ? saveSeenThisKeyword || seenThisKeyword : saveSeenThisKeyword;
seenThisKeyword = containerFlags & ContainerFlags.PropagatesThisKeyword ? saveSeenThisKeyword || seenThisKeyword : saveSeenThisKeyword;
}
else if (containerFlags & ContainerFlags.IsInterface) {
const saveSeenThisKeyword = seenThisKeyword;
@ -3845,6 +3846,7 @@ export function getContainerFlags(node: Node): ContainerFlags {
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.ClassStaticBlockDeclaration:
return ContainerFlags.IsContainer | ContainerFlags.IsControlFlowContainer | ContainerFlags.HasLocals | ContainerFlags.IsFunctionLike;
case SyntaxKind.MethodSignature:
case SyntaxKind.CallSignature:
case SyntaxKind.JSDocSignature:
@ -3852,16 +3854,18 @@ export function getContainerFlags(node: Node): ContainerFlags {
case SyntaxKind.FunctionType:
case SyntaxKind.ConstructSignature:
case SyntaxKind.ConstructorType:
return ContainerFlags.IsContainer | ContainerFlags.HasLocals | ContainerFlags.IsFunctionLike;
return ContainerFlags.IsContainer | ContainerFlags.IsControlFlowContainer | ContainerFlags.HasLocals | ContainerFlags.IsFunctionLike | ContainerFlags.PropagatesThisKeyword;
case SyntaxKind.JSDocImportTag:
// treat as a container to prevent using an enclosing effective host, ensuring import bindings are scoped correctly
return ContainerFlags.IsContainer | ContainerFlags.HasLocals;
return ContainerFlags.IsContainer | ContainerFlags.IsControlFlowContainer | ContainerFlags.HasLocals | ContainerFlags.PropagatesThisKeyword;
case SyntaxKind.FunctionExpression:
case SyntaxKind.ArrowFunction:
return ContainerFlags.IsContainer | ContainerFlags.IsControlFlowContainer | ContainerFlags.HasLocals | ContainerFlags.IsFunctionLike | ContainerFlags.IsFunctionExpression;
case SyntaxKind.ArrowFunction:
return ContainerFlags.IsContainer | ContainerFlags.IsControlFlowContainer | ContainerFlags.HasLocals | ContainerFlags.IsFunctionLike | ContainerFlags.IsFunctionExpression | ContainerFlags.PropagatesThisKeyword;
case SyntaxKind.ModuleBlock:
return ContainerFlags.IsControlFlowContainer;

View File

@ -0,0 +1,52 @@
controlFlowForFunctionLike1.ts(10,12): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'.
controlFlowForFunctionLike1.ts(31,10): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'.
==== controlFlowForFunctionLike1.ts (2 errors) ====
function test1(a: number | string) {
if (typeof a === "number") {
const fn = (arg: typeof a) => true;
return fn;
}
return;
}
test1(0)?.(100);
test1(0)?.("");
~~
!!! error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'.
function test2(a: number | string) {
if (typeof a === "number") {
const fn: { (arg: typeof a): boolean; } = () => true;
return fn;
}
return;
}
test2(0)?.(100);
test2(0)?.("");
function test3(a: number | string) {
if (typeof a === "number") {
return (arg: typeof a) => {};
}
throw new Error("");
}
test3(1)(100);
test3(1)("");
~~
!!! error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'.
function test4(a: number | string) {
let fn = (arg: typeof a) => {};
if (Math.random() && typeof a === "number") {
return fn;
}
throw new Error("");
}
test4(1)?.(100);
test4(1)?.("");

View File

@ -0,0 +1,100 @@
//// [tests/cases/compiler/controlFlowForFunctionLike1.ts] ////
=== controlFlowForFunctionLike1.ts ===
function test1(a: number | string) {
>test1 : Symbol(test1, Decl(controlFlowForFunctionLike1.ts, 0, 0))
>a : Symbol(a, Decl(controlFlowForFunctionLike1.ts, 0, 15))
if (typeof a === "number") {
>a : Symbol(a, Decl(controlFlowForFunctionLike1.ts, 0, 15))
const fn = (arg: typeof a) => true;
>fn : Symbol(fn, Decl(controlFlowForFunctionLike1.ts, 2, 9))
>arg : Symbol(arg, Decl(controlFlowForFunctionLike1.ts, 2, 16))
>a : Symbol(a, Decl(controlFlowForFunctionLike1.ts, 0, 15))
return fn;
>fn : Symbol(fn, Decl(controlFlowForFunctionLike1.ts, 2, 9))
}
return;
}
test1(0)?.(100);
>test1 : Symbol(test1, Decl(controlFlowForFunctionLike1.ts, 0, 0))
test1(0)?.("");
>test1 : Symbol(test1, Decl(controlFlowForFunctionLike1.ts, 0, 0))
function test2(a: number | string) {
>test2 : Symbol(test2, Decl(controlFlowForFunctionLike1.ts, 9, 15))
>a : Symbol(a, Decl(controlFlowForFunctionLike1.ts, 11, 15))
if (typeof a === "number") {
>a : Symbol(a, Decl(controlFlowForFunctionLike1.ts, 11, 15))
const fn: { (arg: typeof a): boolean; } = () => true;
>fn : Symbol(fn, Decl(controlFlowForFunctionLike1.ts, 13, 9))
>arg : Symbol(arg, Decl(controlFlowForFunctionLike1.ts, 13, 17))
>a : Symbol(a, Decl(controlFlowForFunctionLike1.ts, 11, 15))
return fn;
>fn : Symbol(fn, Decl(controlFlowForFunctionLike1.ts, 13, 9))
}
return;
}
test2(0)?.(100);
>test2 : Symbol(test2, Decl(controlFlowForFunctionLike1.ts, 9, 15))
test2(0)?.("");
>test2 : Symbol(test2, Decl(controlFlowForFunctionLike1.ts, 9, 15))
function test3(a: number | string) {
>test3 : Symbol(test3, Decl(controlFlowForFunctionLike1.ts, 20, 15))
>a : Symbol(a, Decl(controlFlowForFunctionLike1.ts, 22, 15))
if (typeof a === "number") {
>a : Symbol(a, Decl(controlFlowForFunctionLike1.ts, 22, 15))
return (arg: typeof a) => {};
>arg : Symbol(arg, Decl(controlFlowForFunctionLike1.ts, 24, 12))
>a : Symbol(a, Decl(controlFlowForFunctionLike1.ts, 22, 15))
}
throw new Error("");
>Error : Symbol(Error, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2022.error.d.ts, --, --))
}
test3(1)(100);
>test3 : Symbol(test3, Decl(controlFlowForFunctionLike1.ts, 20, 15))
test3(1)("");
>test3 : Symbol(test3, Decl(controlFlowForFunctionLike1.ts, 20, 15))
function test4(a: number | string) {
>test4 : Symbol(test4, Decl(controlFlowForFunctionLike1.ts, 30, 13))
>a : Symbol(a, Decl(controlFlowForFunctionLike1.ts, 32, 15))
let fn = (arg: typeof a) => {};
>fn : Symbol(fn, Decl(controlFlowForFunctionLike1.ts, 33, 5))
>arg : Symbol(arg, Decl(controlFlowForFunctionLike1.ts, 33, 12))
>a : Symbol(a, Decl(controlFlowForFunctionLike1.ts, 32, 15))
if (Math.random() && typeof a === "number") {
>Math.random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --))
>Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
>random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --))
>a : Symbol(a, Decl(controlFlowForFunctionLike1.ts, 32, 15))
return fn;
>fn : Symbol(fn, Decl(controlFlowForFunctionLike1.ts, 33, 5))
}
throw new Error("");
>Error : Symbol(Error, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2022.error.d.ts, --, --))
}
test4(1)?.(100);
>test4 : Symbol(test4, Decl(controlFlowForFunctionLike1.ts, 30, 13))
test4(1)?.("");
>test4 : Symbol(test4, Decl(controlFlowForFunctionLike1.ts, 30, 13))

View File

@ -0,0 +1,251 @@
//// [tests/cases/compiler/controlFlowForFunctionLike1.ts] ////
=== controlFlowForFunctionLike1.ts ===
function test1(a: number | string) {
>test1 : (a: number | string) => ((arg: typeof a) => boolean) | undefined
> : ^ ^^ ^^^^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^
>a : string | number
> : ^^^^^^^^^^^^^^^
if (typeof a === "number") {
>typeof a === "number" : boolean
> : ^^^^^^^
>typeof a : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>a : string | number
> : ^^^^^^^^^^^^^^^
>"number" : "number"
> : ^^^^^^^^
const fn = (arg: typeof a) => true;
>fn : (arg: typeof a) => boolean
> : ^ ^^ ^^^^^^^^^^^^
>(arg: typeof a) => true : (arg: typeof a) => boolean
> : ^ ^^ ^^^^^^^^^^^^
>arg : number
> : ^^^^^^
>a : number
> : ^^^^^^
>true : true
> : ^^^^
return fn;
>fn : (arg: typeof a) => boolean
> : ^ ^^ ^^^^^^^^^^^^
}
return;
}
test1(0)?.(100);
>test1(0)?.(100) : boolean | undefined
> : ^^^^^^^^^^^^^^^^^^^
>test1(0) : ((arg: number) => boolean) | undefined
> : ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>test1 : (a: number | string) => ((arg: typeof a) => boolean) | undefined
> : ^ ^^ ^^^^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^
>0 : 0
> : ^
>100 : 100
> : ^^^
test1(0)?.("");
>test1(0)?.("") : boolean | undefined
> : ^^^^^^^^^^^^^^^^^^^
>test1(0) : ((arg: number) => boolean) | undefined
> : ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>test1 : (a: number | string) => ((arg: typeof a) => boolean) | undefined
> : ^ ^^ ^^^^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^
>0 : 0
> : ^
>"" : ""
> : ^^
function test2(a: number | string) {
>test2 : (a: number | string) => ((arg: typeof a) => boolean) | undefined
> : ^ ^^ ^^^^^^^ ^^ ^^^^^ ^^^^^^^^^^^^^
>a : string | number
> : ^^^^^^^^^^^^^^^
if (typeof a === "number") {
>typeof a === "number" : boolean
> : ^^^^^^^
>typeof a : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>a : string | number
> : ^^^^^^^^^^^^^^^
>"number" : "number"
> : ^^^^^^^^
const fn: { (arg: typeof a): boolean; } = () => true;
>fn : (arg: typeof a) => boolean
> : ^ ^^ ^^^^^
>arg : string | number
> : ^^^^^^^^^^^^^^^
>a : string | number
> : ^^^^^^^^^^^^^^^
>() => true : () => true
> : ^^^^^^^^^^
>true : true
> : ^^^^
return fn;
>fn : (arg: typeof a) => boolean
> : ^ ^^ ^^^^^
}
return;
}
test2(0)?.(100);
>test2(0)?.(100) : boolean | undefined
> : ^^^^^^^^^^^^^^^^^^^
>test2(0) : ((arg: string | number) => boolean) | undefined
> : ^^ ^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^
>test2 : (a: number | string) => ((arg: typeof a) => boolean) | undefined
> : ^ ^^ ^^^^^^^ ^^ ^^^^^ ^^^^^^^^^^^^^
>0 : 0
> : ^
>100 : 100
> : ^^^
test2(0)?.("");
>test2(0)?.("") : boolean | undefined
> : ^^^^^^^^^^^^^^^^^^^
>test2(0) : ((arg: string | number) => boolean) | undefined
> : ^^ ^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^
>test2 : (a: number | string) => ((arg: typeof a) => boolean) | undefined
> : ^ ^^ ^^^^^^^ ^^ ^^^^^ ^^^^^^^^^^^^^
>0 : 0
> : ^
>"" : ""
> : ^^
function test3(a: number | string) {
>test3 : (a: number | string) => (arg: typeof a) => void
> : ^ ^^ ^^^^^^ ^^ ^^^^^^^^^
>a : string | number
> : ^^^^^^^^^^^^^^^
if (typeof a === "number") {
>typeof a === "number" : boolean
> : ^^^^^^^
>typeof a : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>a : string | number
> : ^^^^^^^^^^^^^^^
>"number" : "number"
> : ^^^^^^^^
return (arg: typeof a) => {};
>(arg: typeof a) => {} : (arg: typeof a) => void
> : ^ ^^ ^^^^^^^^^
>arg : number
> : ^^^^^^
>a : number
> : ^^^^^^
}
throw new Error("");
>new Error("") : Error
> : ^^^^^
>Error : ErrorConstructor
> : ^^^^^^^^^^^^^^^^
>"" : ""
> : ^^
}
test3(1)(100);
>test3(1)(100) : void
> : ^^^^
>test3(1) : (arg: number) => void
> : ^ ^^^^^^^^^^^^^^^^^
>test3 : (a: number | string) => (arg: typeof a) => void
> : ^ ^^ ^^^^^^ ^^ ^^^^^^^^^
>1 : 1
> : ^
>100 : 100
> : ^^^
test3(1)("");
>test3(1)("") : void
> : ^^^^
>test3(1) : (arg: number) => void
> : ^ ^^^^^^^^^^^^^^^^^
>test3 : (a: number | string) => (arg: typeof a) => void
> : ^ ^^ ^^^^^^ ^^ ^^^^^^^^^
>1 : 1
> : ^
>"" : ""
> : ^^
function test4(a: number | string) {
>test4 : (a: number | string) => (arg: typeof a) => void
> : ^ ^^ ^^^^^^ ^^ ^^^^^^^^^
>a : string | number
> : ^^^^^^^^^^^^^^^
let fn = (arg: typeof a) => {};
>fn : (arg: typeof a) => void
> : ^ ^^ ^^^^^^^^^
>(arg: typeof a) => {} : (arg: typeof a) => void
> : ^ ^^ ^^^^^^^^^
>arg : string | number
> : ^^^^^^^^^^^^^^^
>a : string | number
> : ^^^^^^^^^^^^^^^
if (Math.random() && typeof a === "number") {
>Math.random() && typeof a === "number" : boolean | 0
> : ^^^^^^^^^^^
>Math.random() : number
> : ^^^^^^
>Math.random : () => number
> : ^^^^^^
>Math : Math
> : ^^^^
>random : () => number
> : ^^^^^^
>typeof a === "number" : boolean
> : ^^^^^^^
>typeof a : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>a : string | number
> : ^^^^^^^^^^^^^^^
>"number" : "number"
> : ^^^^^^^^
return fn;
>fn : (arg: typeof a) => void
> : ^ ^^ ^^^^^^^^^
}
throw new Error("");
>new Error("") : Error
> : ^^^^^
>Error : ErrorConstructor
> : ^^^^^^^^^^^^^^^^
>"" : ""
> : ^^
}
test4(1)?.(100);
>test4(1)?.(100) : void
> : ^^^^
>test4(1) : (arg: string | number) => void
> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^
>test4 : (a: number | string) => (arg: typeof a) => void
> : ^ ^^ ^^^^^^ ^^ ^^^^^^^^^
>1 : 1
> : ^
>100 : 100
> : ^^^
test4(1)?.("");
>test4(1)?.("") : void
> : ^^^^
>test4(1) : (arg: string | number) => void
> : ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^
>test4 : (a: number | string) => (arg: typeof a) => void
> : ^ ^^ ^^^^^^ ^^ ^^^^^^^^^
>1 : 1
> : ^
>"" : ""
> : ^^

View File

@ -0,0 +1,210 @@
controlFlowFunctionLikeCircular_1.ts(1,1): error TS2448: Block-scoped variable 'unionOfDifferentReturnType1' used before its declaration.
controlFlowFunctionLikeCircular_1.ts(1,1): error TS2454: Variable 'unionOfDifferentReturnType1' is used before being assigned.
controlFlowFunctionLikeCircular_1.ts(1,29): error TS2345: Argument of type 'boolean' is not assignable to parameter of type 'number'.
controlFlowFunctionLikeCircular_1.ts(2,7): error TS1155: 'const' declarations must be initialized.
controlFlowFunctionLikeCircular_1.ts(2,7): error TS2451: Cannot redeclare block-scoped variable 'unionOfDifferentReturnType1'.
controlFlowFunctionLikeCircular_10.ts(1,10): error TS2393: Duplicate function implementation.
controlFlowFunctionLikeCircular_10.ts(3,5): error TS2448: Block-scoped variable 'o' used before its declaration.
controlFlowFunctionLikeCircular_10.ts(3,5): error TS2454: Variable 'o' is used before being assigned.
controlFlowFunctionLikeCircular_2.ts(1,29): error TS2345: Argument of type 'boolean' is not assignable to parameter of type 'number'.
controlFlowFunctionLikeCircular_2.ts(2,7): error TS2451: Cannot redeclare block-scoped variable 'unionOfDifferentReturnType1'.
controlFlowFunctionLikeCircular_3.ts(1,10): error TS2393: Duplicate function implementation.
controlFlowFunctionLikeCircular_3.ts(2,3): error TS2448: Block-scoped variable 'fn' used before its declaration.
controlFlowFunctionLikeCircular_3.ts(3,9): error TS2502: 'fn' is referenced directly or indirectly in its own type annotation.
controlFlowFunctionLikeCircular_3.ts(3,51): error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value.
controlFlowFunctionLikeCircular_3.ts(3,58): error TS2749: 'arg' refers to a value, but is being used as a type here. Did you mean 'typeof arg'?
controlFlowFunctionLikeCircular_4.ts(1,10): error TS2393: Duplicate function implementation.
controlFlowFunctionLikeCircular_4.ts(2,3): error TS2448: Block-scoped variable 'fn' used before its declaration.
controlFlowFunctionLikeCircular_4.ts(2,3): error TS2454: Variable 'fn' is used before being assigned.
controlFlowFunctionLikeCircular_4.ts(3,40): error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value.
controlFlowFunctionLikeCircular_4.ts(3,47): error TS2749: 'arg' refers to a value, but is being used as a type here. Did you mean 'typeof arg'?
controlFlowFunctionLikeCircular_5.ts(1,10): error TS2393: Duplicate function implementation.
controlFlowFunctionLikeCircular_5.ts(3,5): error TS2448: Block-scoped variable 'fn' used before its declaration.
controlFlowFunctionLikeCircular_5.ts(3,5): error TS2454: Variable 'fn' is used before being assigned.
controlFlowFunctionLikeCircular_6.ts(1,10): error TS2393: Duplicate function implementation.
controlFlowFunctionLikeCircular_6.ts(3,5): error TS2448: Block-scoped variable 'fn' used before its declaration.
controlFlowFunctionLikeCircular_6.ts(3,5): error TS2454: Variable 'fn' is used before being assigned.
controlFlowFunctionLikeCircular_7.ts(1,10): error TS2393: Duplicate function implementation.
controlFlowFunctionLikeCircular_7.ts(3,5): error TS2448: Block-scoped variable 'fn' used before its declaration.
controlFlowFunctionLikeCircular_7.ts(3,5): error TS2454: Variable 'fn' is used before being assigned.
controlFlowFunctionLikeCircular_8.ts(1,10): error TS2393: Duplicate function implementation.
controlFlowFunctionLikeCircular_8.ts(3,5): error TS2448: Block-scoped variable 'b' used before its declaration.
controlFlowFunctionLikeCircular_8.ts(3,5): error TS2454: Variable 'b' is used before being assigned.
controlFlowFunctionLikeCircular_8.ts(3,5): error TS2554: Expected 1 arguments, but got 0.
controlFlowFunctionLikeCircular_8.ts(4,10): error TS2456: Type alias 'First' circularly references itself.
controlFlowFunctionLikeCircular_9.ts(1,10): error TS2393: Duplicate function implementation.
controlFlowFunctionLikeCircular_9.ts(3,5): error TS2448: Block-scoped variable 'o' used before its declaration.
controlFlowFunctionLikeCircular_9.ts(3,5): error TS2454: Variable 'o' is used before being assigned.
controlFlowFunctionLikeCircular_9.ts(4,47): error TS2411: Property 'x' of type '(() => DateConstructor) | (() => void)' is not assignable to 'string' index type '() => string | number'.
==== controlFlowFunctionLikeCircular_1.ts (5 errors) ====
unionOfDifferentReturnType1(true);
~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2448: Block-scoped variable 'unionOfDifferentReturnType1' used before its declaration.
!!! related TS2728 controlFlowFunctionLikeCircular_1.ts:2:7: 'unionOfDifferentReturnType1' is declared here.
~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2454: Variable 'unionOfDifferentReturnType1' is used before being assigned.
~~~~
!!! error TS2345: Argument of type 'boolean' is not assignable to parameter of type 'number'.
const unionOfDifferentReturnType1: { (a: any): number; } | { (a: number): typeof Date; };
~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS1155: 'const' declarations must be initialized.
~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2451: Cannot redeclare block-scoped variable 'unionOfDifferentReturnType1'.
!!! related TS6203 controlFlowFunctionLikeCircular_2.ts:2:7: 'unionOfDifferentReturnType1' was also declared here.
==== controlFlowFunctionLikeCircular_2.ts (2 errors) ====
unionOfDifferentReturnType1(true);
~~~~
!!! error TS2345: Argument of type 'boolean' is not assignable to parameter of type 'number'.
const unionOfDifferentReturnType1 = Math.random() ? (a: any) => 1 : (a: number) => ({}) as typeof Date;
~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2451: Cannot redeclare block-scoped variable 'unionOfDifferentReturnType1'.
!!! related TS6203 controlFlowFunctionLikeCircular_1.ts:2:7: 'unionOfDifferentReturnType1' was also declared here.
==== controlFlowFunctionLikeCircular_3.ts (5 errors) ====
function test(arg: () => string) {
~~~~
!!! error TS2393: Duplicate function implementation.
fn();
~~
!!! error TS2448: Block-scoped variable 'fn' used before its declaration.
!!! related TS2728 controlFlowFunctionLikeCircular_3.ts:3:9: 'fn' is declared here.
const fn: typeof fn = Math.random() ? arg : (): (() => arg) => {};
~~
!!! error TS2502: 'fn' is referenced directly or indirectly in its own type annotation.
~~~~~~~~~~~
!!! error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value.
~~~
!!! error TS2749: 'arg' refers to a value, but is being used as a type here. Did you mean 'typeof arg'?
}
==== controlFlowFunctionLikeCircular_4.ts (5 errors) ====
function test(arg: () => string) {
~~~~
!!! error TS2393: Duplicate function implementation.
fn();
~~
!!! error TS2448: Block-scoped variable 'fn' used before its declaration.
!!! related TS2728 controlFlowFunctionLikeCircular_4.ts:3:9: 'fn' is declared here.
~~
!!! error TS2454: Variable 'fn' is used before being assigned.
const fn = Math.random() ? arg : (): (() => arg) => {};
~~~~~~~~~~~
!!! error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value.
~~~
!!! error TS2749: 'arg' refers to a value, but is being used as a type here. Did you mean 'typeof arg'?
}
==== controlFlowFunctionLikeCircular_5.ts (3 errors) ====
function test(arg: string | number) {
~~~~
!!! error TS2393: Duplicate function implementation.
if (typeof arg === "string") {
fn();
~~
!!! error TS2448: Block-scoped variable 'fn' used before its declaration.
!!! related TS2728 controlFlowFunctionLikeCircular_5.ts:4:11: 'fn' is declared here.
~~
!!! error TS2454: Variable 'fn' is used before being assigned.
const fn: () => typeof arg = () => arg;
return fn;
}
return undefined;
}
==== controlFlowFunctionLikeCircular_6.ts (3 errors) ====
function test(arg: string | number) {
~~~~
!!! error TS2393: Duplicate function implementation.
if (typeof arg === "string") {
fn();
~~
!!! error TS2448: Block-scoped variable 'fn' used before its declaration.
!!! related TS2728 controlFlowFunctionLikeCircular_6.ts:4:11: 'fn' is declared here.
~~
!!! error TS2454: Variable 'fn' is used before being assigned.
const fn = (): typeof arg => arg;
return fn;
}
return undefined;
}
==== controlFlowFunctionLikeCircular_7.ts (3 errors) ====
function test(arg: string | number) {
~~~~
!!! error TS2393: Duplicate function implementation.
if (typeof arg === "string") {
fn();
~~
!!! error TS2448: Block-scoped variable 'fn' used before its declaration.
!!! related TS2728 controlFlowFunctionLikeCircular_7.ts:4:11: 'fn' is declared here.
~~
!!! error TS2454: Variable 'fn' is used before being assigned.
const fn: { (): typeof arg } = () => arg;
return fn;
}
return undefined;
}
==== controlFlowFunctionLikeCircular_8.ts (5 errors) ====
function test(arg: string | number, whatever: any) {
~~~~
!!! error TS2393: Duplicate function implementation.
if (typeof arg === "string") {
b();
~
!!! error TS2448: Block-scoped variable 'b' used before its declaration.
!!! related TS2728 controlFlowFunctionLikeCircular_8.ts:6:11: 'b' is declared here.
~
!!! error TS2454: Variable 'b' is used before being assigned.
~
!!! error TS2554: Expected 1 arguments, but got 0.
!!! related TS6210 controlFlowFunctionLikeCircular_8.ts:5:18: An argument for 'arg' was not provided.
type First = typeof arg;
~~~~~
!!! error TS2456: Type alias 'First' circularly references itself.
type Test = (arg: unknown) => arg is First;
const b: Test = whatever;
return b;
}
return undefined;
}
==== controlFlowFunctionLikeCircular_9.ts (4 errors) ====
function test(arg: string | number, whatever: any) {
~~~~
!!! error TS2393: Duplicate function implementation.
if (typeof arg === "string") {
o.x();
~
!!! error TS2448: Block-scoped variable 'o' used before its declaration.
!!! related TS2728 controlFlowFunctionLikeCircular_9.ts:4:11: 'o' is declared here.
~
!!! error TS2454: Variable 'o' is used before being assigned.
const o: { [k: string]: () => typeof arg; x: (() => typeof Date) | (() => void) } = whatever
~
!!! error TS2411: Property 'x' of type '(() => DateConstructor) | (() => void)' is not assignable to 'string' index type '() => string | number'.
return o.x;
}
return undefined;
}
==== controlFlowFunctionLikeCircular_10.ts (3 errors) ====
function test(arg: string | number, whatever: any) {
~~~~
!!! error TS2393: Duplicate function implementation.
if (typeof arg === "string") {
o.foo();
~
!!! error TS2448: Block-scoped variable 'o' used before its declaration.
!!! related TS2728 controlFlowFunctionLikeCircular_10.ts:4:11: 'o' is declared here.
~
!!! error TS2454: Variable 'o' is used before being assigned.
const o: { [k: string]: () => typeof arg } = whatever
return o.foo;
}
return undefined;
}

View File

@ -0,0 +1,223 @@
//// [tests/cases/compiler/controlFlowFunctionLikeCircular1.ts] ////
=== controlFlowFunctionLikeCircular_1.ts ===
unionOfDifferentReturnType1(true);
>unionOfDifferentReturnType1 : Symbol(unionOfDifferentReturnType1, Decl(controlFlowFunctionLikeCircular_1.ts, 1, 5))
const unionOfDifferentReturnType1: { (a: any): number; } | { (a: number): typeof Date; };
>unionOfDifferentReturnType1 : Symbol(unionOfDifferentReturnType1, Decl(controlFlowFunctionLikeCircular_1.ts, 1, 5))
>a : Symbol(a, Decl(controlFlowFunctionLikeCircular_1.ts, 1, 38))
>a : Symbol(a, Decl(controlFlowFunctionLikeCircular_1.ts, 1, 62))
>Date : Symbol(Date, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.scripthost.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --) ... and 1 more)
=== controlFlowFunctionLikeCircular_2.ts ===
unionOfDifferentReturnType1(true);
>unionOfDifferentReturnType1 : Symbol(unionOfDifferentReturnType1, Decl(controlFlowFunctionLikeCircular_1.ts, 1, 5))
const unionOfDifferentReturnType1 = Math.random() ? (a: any) => 1 : (a: number) => ({}) as typeof Date;
>unionOfDifferentReturnType1 : Symbol(unionOfDifferentReturnType1, Decl(controlFlowFunctionLikeCircular_2.ts, 1, 5))
>Math.random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --))
>Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
>random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --))
>a : Symbol(a, Decl(controlFlowFunctionLikeCircular_2.ts, 1, 53))
>a : Symbol(a, Decl(controlFlowFunctionLikeCircular_2.ts, 1, 69))
>Date : Symbol(Date, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.scripthost.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --) ... and 1 more)
=== controlFlowFunctionLikeCircular_3.ts ===
function test(arg: () => string) {
>test : Symbol(test, Decl(controlFlowFunctionLikeCircular_3.ts, 0, 0), Decl(controlFlowFunctionLikeCircular_4.ts, 0, 0), Decl(controlFlowFunctionLikeCircular_5.ts, 0, 0), Decl(controlFlowFunctionLikeCircular_6.ts, 0, 0), Decl(controlFlowFunctionLikeCircular_7.ts, 0, 0) ... and 3 more)
>arg : Symbol(arg, Decl(controlFlowFunctionLikeCircular_3.ts, 0, 14))
fn();
>fn : Symbol(fn, Decl(controlFlowFunctionLikeCircular_3.ts, 2, 7))
const fn: typeof fn = Math.random() ? arg : (): (() => arg) => {};
>fn : Symbol(fn, Decl(controlFlowFunctionLikeCircular_3.ts, 2, 7))
>fn : Symbol(fn, Decl(controlFlowFunctionLikeCircular_3.ts, 2, 7))
>Math.random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --))
>Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
>random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --))
>arg : Symbol(arg, Decl(controlFlowFunctionLikeCircular_3.ts, 0, 14))
>arg : Symbol(arg)
}
=== controlFlowFunctionLikeCircular_4.ts ===
function test(arg: () => string) {
>test : Symbol(test, Decl(controlFlowFunctionLikeCircular_3.ts, 0, 0), Decl(controlFlowFunctionLikeCircular_4.ts, 0, 0), Decl(controlFlowFunctionLikeCircular_5.ts, 0, 0), Decl(controlFlowFunctionLikeCircular_6.ts, 0, 0), Decl(controlFlowFunctionLikeCircular_7.ts, 0, 0) ... and 3 more)
>arg : Symbol(arg, Decl(controlFlowFunctionLikeCircular_4.ts, 0, 14))
fn();
>fn : Symbol(fn, Decl(controlFlowFunctionLikeCircular_4.ts, 2, 7))
const fn = Math.random() ? arg : (): (() => arg) => {};
>fn : Symbol(fn, Decl(controlFlowFunctionLikeCircular_4.ts, 2, 7))
>Math.random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --))
>Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
>random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --))
>arg : Symbol(arg, Decl(controlFlowFunctionLikeCircular_4.ts, 0, 14))
>arg : Symbol(arg)
}
=== controlFlowFunctionLikeCircular_5.ts ===
function test(arg: string | number) {
>test : Symbol(test, Decl(controlFlowFunctionLikeCircular_3.ts, 0, 0), Decl(controlFlowFunctionLikeCircular_4.ts, 0, 0), Decl(controlFlowFunctionLikeCircular_5.ts, 0, 0), Decl(controlFlowFunctionLikeCircular_6.ts, 0, 0), Decl(controlFlowFunctionLikeCircular_7.ts, 0, 0) ... and 3 more)
>arg : Symbol(arg, Decl(controlFlowFunctionLikeCircular_5.ts, 0, 14))
if (typeof arg === "string") {
>arg : Symbol(arg, Decl(controlFlowFunctionLikeCircular_5.ts, 0, 14))
fn();
>fn : Symbol(fn, Decl(controlFlowFunctionLikeCircular_5.ts, 3, 9))
const fn: () => typeof arg = () => arg;
>fn : Symbol(fn, Decl(controlFlowFunctionLikeCircular_5.ts, 3, 9))
>arg : Symbol(arg, Decl(controlFlowFunctionLikeCircular_5.ts, 0, 14))
>arg : Symbol(arg, Decl(controlFlowFunctionLikeCircular_5.ts, 0, 14))
return fn;
>fn : Symbol(fn, Decl(controlFlowFunctionLikeCircular_5.ts, 3, 9))
}
return undefined;
>undefined : Symbol(undefined)
}
=== controlFlowFunctionLikeCircular_6.ts ===
function test(arg: string | number) {
>test : Symbol(test, Decl(controlFlowFunctionLikeCircular_3.ts, 0, 0), Decl(controlFlowFunctionLikeCircular_4.ts, 0, 0), Decl(controlFlowFunctionLikeCircular_5.ts, 0, 0), Decl(controlFlowFunctionLikeCircular_6.ts, 0, 0), Decl(controlFlowFunctionLikeCircular_7.ts, 0, 0) ... and 3 more)
>arg : Symbol(arg, Decl(controlFlowFunctionLikeCircular_6.ts, 0, 14))
if (typeof arg === "string") {
>arg : Symbol(arg, Decl(controlFlowFunctionLikeCircular_6.ts, 0, 14))
fn();
>fn : Symbol(fn, Decl(controlFlowFunctionLikeCircular_6.ts, 3, 9))
const fn = (): typeof arg => arg;
>fn : Symbol(fn, Decl(controlFlowFunctionLikeCircular_6.ts, 3, 9))
>arg : Symbol(arg, Decl(controlFlowFunctionLikeCircular_6.ts, 0, 14))
>arg : Symbol(arg, Decl(controlFlowFunctionLikeCircular_6.ts, 0, 14))
return fn;
>fn : Symbol(fn, Decl(controlFlowFunctionLikeCircular_6.ts, 3, 9))
}
return undefined;
>undefined : Symbol(undefined)
}
=== controlFlowFunctionLikeCircular_7.ts ===
function test(arg: string | number) {
>test : Symbol(test, Decl(controlFlowFunctionLikeCircular_3.ts, 0, 0), Decl(controlFlowFunctionLikeCircular_4.ts, 0, 0), Decl(controlFlowFunctionLikeCircular_5.ts, 0, 0), Decl(controlFlowFunctionLikeCircular_6.ts, 0, 0), Decl(controlFlowFunctionLikeCircular_7.ts, 0, 0) ... and 3 more)
>arg : Symbol(arg, Decl(controlFlowFunctionLikeCircular_7.ts, 0, 14))
if (typeof arg === "string") {
>arg : Symbol(arg, Decl(controlFlowFunctionLikeCircular_7.ts, 0, 14))
fn();
>fn : Symbol(fn, Decl(controlFlowFunctionLikeCircular_7.ts, 3, 9))
const fn: { (): typeof arg } = () => arg;
>fn : Symbol(fn, Decl(controlFlowFunctionLikeCircular_7.ts, 3, 9))
>arg : Symbol(arg, Decl(controlFlowFunctionLikeCircular_7.ts, 0, 14))
>arg : Symbol(arg, Decl(controlFlowFunctionLikeCircular_7.ts, 0, 14))
return fn;
>fn : Symbol(fn, Decl(controlFlowFunctionLikeCircular_7.ts, 3, 9))
}
return undefined;
>undefined : Symbol(undefined)
}
=== controlFlowFunctionLikeCircular_8.ts ===
function test(arg: string | number, whatever: any) {
>test : Symbol(test, Decl(controlFlowFunctionLikeCircular_3.ts, 0, 0), Decl(controlFlowFunctionLikeCircular_4.ts, 0, 0), Decl(controlFlowFunctionLikeCircular_5.ts, 0, 0), Decl(controlFlowFunctionLikeCircular_6.ts, 0, 0), Decl(controlFlowFunctionLikeCircular_7.ts, 0, 0) ... and 3 more)
>arg : Symbol(arg, Decl(controlFlowFunctionLikeCircular_8.ts, 0, 14))
>whatever : Symbol(whatever, Decl(controlFlowFunctionLikeCircular_8.ts, 0, 35))
if (typeof arg === "string") {
>arg : Symbol(arg, Decl(controlFlowFunctionLikeCircular_8.ts, 0, 14))
b();
>b : Symbol(b, Decl(controlFlowFunctionLikeCircular_8.ts, 5, 9))
type First = typeof arg;
>First : Symbol(First, Decl(controlFlowFunctionLikeCircular_8.ts, 2, 8))
>arg : Symbol(arg, Decl(controlFlowFunctionLikeCircular_8.ts, 0, 14))
type Test = (arg: unknown) => arg is First;
>Test : Symbol(Test, Decl(controlFlowFunctionLikeCircular_8.ts, 3, 28))
>arg : Symbol(arg, Decl(controlFlowFunctionLikeCircular_8.ts, 4, 17))
>arg : Symbol(arg, Decl(controlFlowFunctionLikeCircular_8.ts, 4, 17))
>First : Symbol(First, Decl(controlFlowFunctionLikeCircular_8.ts, 2, 8))
const b: Test = whatever;
>b : Symbol(b, Decl(controlFlowFunctionLikeCircular_8.ts, 5, 9))
>Test : Symbol(Test, Decl(controlFlowFunctionLikeCircular_8.ts, 3, 28))
>whatever : Symbol(whatever, Decl(controlFlowFunctionLikeCircular_8.ts, 0, 35))
return b;
>b : Symbol(b, Decl(controlFlowFunctionLikeCircular_8.ts, 5, 9))
}
return undefined;
>undefined : Symbol(undefined)
}
=== controlFlowFunctionLikeCircular_9.ts ===
function test(arg: string | number, whatever: any) {
>test : Symbol(test, Decl(controlFlowFunctionLikeCircular_3.ts, 0, 0), Decl(controlFlowFunctionLikeCircular_4.ts, 0, 0), Decl(controlFlowFunctionLikeCircular_5.ts, 0, 0), Decl(controlFlowFunctionLikeCircular_6.ts, 0, 0), Decl(controlFlowFunctionLikeCircular_7.ts, 0, 0) ... and 3 more)
>arg : Symbol(arg, Decl(controlFlowFunctionLikeCircular_9.ts, 0, 14))
>whatever : Symbol(whatever, Decl(controlFlowFunctionLikeCircular_9.ts, 0, 35))
if (typeof arg === "string") {
>arg : Symbol(arg, Decl(controlFlowFunctionLikeCircular_9.ts, 0, 14))
o.x();
>o.x : Symbol(x, Decl(controlFlowFunctionLikeCircular_9.ts, 3, 45))
>o : Symbol(o, Decl(controlFlowFunctionLikeCircular_9.ts, 3, 9))
>x : Symbol(x, Decl(controlFlowFunctionLikeCircular_9.ts, 3, 45))
const o: { [k: string]: () => typeof arg; x: (() => typeof Date) | (() => void) } = whatever
>o : Symbol(o, Decl(controlFlowFunctionLikeCircular_9.ts, 3, 9))
>k : Symbol(k, Decl(controlFlowFunctionLikeCircular_9.ts, 3, 16))
>arg : Symbol(arg, Decl(controlFlowFunctionLikeCircular_9.ts, 0, 14))
>x : Symbol(x, Decl(controlFlowFunctionLikeCircular_9.ts, 3, 45))
>Date : Symbol(Date, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.scripthost.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --) ... and 1 more)
>whatever : Symbol(whatever, Decl(controlFlowFunctionLikeCircular_9.ts, 0, 35))
return o.x;
>o.x : Symbol(x, Decl(controlFlowFunctionLikeCircular_9.ts, 3, 45))
>o : Symbol(o, Decl(controlFlowFunctionLikeCircular_9.ts, 3, 9))
>x : Symbol(x, Decl(controlFlowFunctionLikeCircular_9.ts, 3, 45))
}
return undefined;
>undefined : Symbol(undefined)
}
=== controlFlowFunctionLikeCircular_10.ts ===
function test(arg: string | number, whatever: any) {
>test : Symbol(test, Decl(controlFlowFunctionLikeCircular_3.ts, 0, 0), Decl(controlFlowFunctionLikeCircular_4.ts, 0, 0), Decl(controlFlowFunctionLikeCircular_5.ts, 0, 0), Decl(controlFlowFunctionLikeCircular_6.ts, 0, 0), Decl(controlFlowFunctionLikeCircular_7.ts, 0, 0) ... and 3 more)
>arg : Symbol(arg, Decl(controlFlowFunctionLikeCircular_10.ts, 0, 14))
>whatever : Symbol(whatever, Decl(controlFlowFunctionLikeCircular_10.ts, 0, 35))
if (typeof arg === "string") {
>arg : Symbol(arg, Decl(controlFlowFunctionLikeCircular_10.ts, 0, 14))
o.foo();
>o.foo : Symbol(__index, Decl(controlFlowFunctionLikeCircular_10.ts, 3, 14))
>o : Symbol(o, Decl(controlFlowFunctionLikeCircular_10.ts, 3, 9))
>foo : Symbol(__index, Decl(controlFlowFunctionLikeCircular_10.ts, 3, 14))
const o: { [k: string]: () => typeof arg } = whatever
>o : Symbol(o, Decl(controlFlowFunctionLikeCircular_10.ts, 3, 9))
>k : Symbol(k, Decl(controlFlowFunctionLikeCircular_10.ts, 3, 16))
>arg : Symbol(arg, Decl(controlFlowFunctionLikeCircular_10.ts, 0, 14))
>whatever : Symbol(whatever, Decl(controlFlowFunctionLikeCircular_10.ts, 0, 35))
return o.foo;
>o.foo : Symbol(__index, Decl(controlFlowFunctionLikeCircular_10.ts, 3, 14))
>o : Symbol(o, Decl(controlFlowFunctionLikeCircular_10.ts, 3, 9))
>foo : Symbol(__index, Decl(controlFlowFunctionLikeCircular_10.ts, 3, 14))
}
return undefined;
>undefined : Symbol(undefined)
}

View File

@ -0,0 +1,414 @@
//// [tests/cases/compiler/controlFlowFunctionLikeCircular1.ts] ////
=== controlFlowFunctionLikeCircular_1.ts ===
unionOfDifferentReturnType1(true);
>unionOfDifferentReturnType1(true) : number | DateConstructor
> : ^^^^^^^^^^^^^^^^^^^^^^^^
>unionOfDifferentReturnType1 : ((a: any) => number) | ((a: number) => typeof Date)
> : ^^ ^^ ^^^^^ ^^^^^^ ^^ ^^^^^ ^
>true : true
> : ^^^^
const unionOfDifferentReturnType1: { (a: any): number; } | { (a: number): typeof Date; };
>unionOfDifferentReturnType1 : ((a: any) => number) | ((a: number) => typeof Date)
> : ^^ ^^ ^^^^^ ^^^^^^ ^^ ^^^^^ ^
>a : any
> : ^^^
>a : number
> : ^^^^^^
>Date : DateConstructor
> : ^^^^^^^^^^^^^^^
=== controlFlowFunctionLikeCircular_2.ts ===
unionOfDifferentReturnType1(true);
>unionOfDifferentReturnType1(true) : number | DateConstructor
> : ^^^^^^^^^^^^^^^^^^^^^^^^
>unionOfDifferentReturnType1 : ((a: any) => number) | ((a: number) => typeof Date)
> : ^^ ^^ ^^^^^ ^^^^^^ ^^ ^^^^^ ^
>true : true
> : ^^^^
const unionOfDifferentReturnType1 = Math.random() ? (a: any) => 1 : (a: number) => ({}) as typeof Date;
>unionOfDifferentReturnType1 : ((a: any) => number) | ((a: number) => typeof Date)
> : ^^ ^^ ^^^^^^^^^^^^^^^^^ ^^ ^^^^^ ^
>Math.random() ? (a: any) => 1 : (a: number) => ({}) as typeof Date : ((a: any) => number) | ((a: number) => typeof Date)
> : ^^ ^^ ^^^^^^^^^^^^^^^^^ ^^ ^^^^^ ^
>Math.random() : number
> : ^^^^^^
>Math.random : () => number
> : ^^^^^^
>Math : Math
> : ^^^^
>random : () => number
> : ^^^^^^
>(a: any) => 1 : (a: any) => number
> : ^ ^^ ^^^^^^^^^^^
>a : any
> : ^^^
>1 : 1
> : ^
>(a: number) => ({}) as typeof Date : (a: number) => typeof Date
> : ^ ^^ ^^^^^
>a : number
> : ^^^^^^
>({}) as typeof Date : DateConstructor
> : ^^^^^^^^^^^^^^^
>({}) : {}
> : ^^
>{} : {}
> : ^^
>Date : DateConstructor
> : ^^^^^^^^^^^^^^^
=== controlFlowFunctionLikeCircular_3.ts ===
function test(arg: () => string) {
>test : { (arg: () => string): void; (arg: () => string): void; (arg: string | number): (() => typeof arg) | undefined; (arg: string | number): (() => typeof arg) | undefined; (arg: string | number): (() => typeof arg) | undefined; (arg: string | number, whatever: any): ((arg: unknown) => arg is any) | undefined; (arg: string | number, whatever: any): (() => void) | undefined; (arg: string | number, whatever: any): (() => typeof arg) | undefined; }
> : ^^^ ^^ ^^^^^^^^^^ ^^ ^^^^^^^^^^ ^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^ ^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^ ^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^ ^^ ^^ ^^ ^^^^^ ^^ ^^^^^ ^^^^^^^^^^^^^^^^^^^ ^^ ^^ ^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^ ^^ ^^ ^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^
>arg : () => string
> : ^^^^^^
fn();
>fn() : any
> : ^^^
>fn : any
> : ^^^
const fn: typeof fn = Math.random() ? arg : (): (() => arg) => {};
>fn : any
> : ^^^
>fn : any
> : ^^^
>Math.random() ? arg : (): (() => arg) => {} : (() => string) | (() => (() => arg))
> : ^^^^^^^ ^^^^^^^^^^^ ^
>Math.random() : number
> : ^^^^^^
>Math.random : () => number
> : ^^^^^^
>Math : Math
> : ^^^^
>random : () => number
> : ^^^^^^
>arg : () => string
> : ^^^^^^
>(): (() => arg) => {} : () => (() => arg)
> : ^^^^^^
}
=== controlFlowFunctionLikeCircular_4.ts ===
function test(arg: () => string) {
>test : { (arg: () => string): void; (arg: () => string): void; (arg: string | number): (() => typeof arg) | undefined; (arg: string | number): (() => typeof arg) | undefined; (arg: string | number): (() => typeof arg) | undefined; (arg: string | number, whatever: any): ((arg: unknown) => arg is any) | undefined; (arg: string | number, whatever: any): (() => void) | undefined; (arg: string | number, whatever: any): (() => typeof arg) | undefined; }
> : ^^^ ^^ ^^^^^^^^^^ ^^ ^^^^^^^^^^ ^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^ ^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^ ^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^ ^^ ^^ ^^ ^^^^^ ^^ ^^^^^ ^^^^^^^^^^^^^^^^^^^ ^^ ^^ ^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^ ^^ ^^ ^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^
>arg : () => string
> : ^^^^^^
fn();
>fn() : string | (() => arg)
> : ^^^^^^^^^^^^^^^^ ^
>fn : (() => string) | (() => (() => arg))
> : ^^^^^^^ ^^^^^^^^^^^ ^
const fn = Math.random() ? arg : (): (() => arg) => {};
>fn : (() => string) | (() => (() => arg))
> : ^^^^^^^ ^^^^^^^^^^^ ^
>Math.random() ? arg : (): (() => arg) => {} : (() => string) | (() => (() => arg))
> : ^^^^^^^ ^^^^^^^^^^^ ^
>Math.random() : number
> : ^^^^^^
>Math.random : () => number
> : ^^^^^^
>Math : Math
> : ^^^^
>random : () => number
> : ^^^^^^
>arg : () => string
> : ^^^^^^
>(): (() => arg) => {} : () => (() => arg)
> : ^^^^^^
}
=== controlFlowFunctionLikeCircular_5.ts ===
function test(arg: string | number) {
>test : { (arg: () => string): void; (arg: () => string): void; (arg: string | number): (() => typeof arg) | undefined; (arg: string | number): (() => typeof arg) | undefined; (arg: string | number): (() => typeof arg) | undefined; (arg: string | number, whatever: any): ((arg: unknown) => arg is any) | undefined; (arg: string | number, whatever: any): (() => void) | undefined; (arg: string | number, whatever: any): (() => typeof arg) | undefined; }
> : ^^^ ^^ ^^^^^^^^^^ ^^ ^^^^^^^^^^ ^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^ ^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^ ^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^ ^^ ^^ ^^ ^^^^^ ^^ ^^^^^ ^^^^^^^^^^^^^^^^^^^ ^^ ^^ ^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^ ^^ ^^ ^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^
>arg : string | number
> : ^^^^^^^^^^^^^^^
if (typeof arg === "string") {
>typeof arg === "string" : boolean
> : ^^^^^^^
>typeof arg : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>arg : string | number
> : ^^^^^^^^^^^^^^^
>"string" : "string"
> : ^^^^^^^^
fn();
>fn() : string | number
> : ^^^^^^^^^^^^^^^
>fn : () => typeof arg
> : ^^^^^^
const fn: () => typeof arg = () => arg;
>fn : () => typeof arg
> : ^^^^^^
>arg : string | number
> : ^^^^^^^^^^^^^^^
>() => arg : () => string
> : ^^^^^^^^^^^^
>arg : string
> : ^^^^^^
return fn;
>fn : () => typeof arg
> : ^^^^^^
}
return undefined;
>undefined : undefined
> : ^^^^^^^^^
}
=== controlFlowFunctionLikeCircular_6.ts ===
function test(arg: string | number) {
>test : { (arg: () => string): void; (arg: () => string): void; (arg: string | number): (() => typeof arg) | undefined; (arg: string | number): (() => typeof arg) | undefined; (arg: string | number): (() => typeof arg) | undefined; (arg: string | number, whatever: any): ((arg: unknown) => arg is any) | undefined; (arg: string | number, whatever: any): (() => void) | undefined; (arg: string | number, whatever: any): (() => typeof arg) | undefined; }
> : ^^^ ^^ ^^^^^^^^^^ ^^ ^^^^^^^^^^ ^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^ ^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^ ^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^ ^^ ^^ ^^ ^^^^^ ^^ ^^^^^ ^^^^^^^^^^^^^^^^^^^ ^^ ^^ ^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^ ^^ ^^ ^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^
>arg : string | number
> : ^^^^^^^^^^^^^^^
if (typeof arg === "string") {
>typeof arg === "string" : boolean
> : ^^^^^^^
>typeof arg : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>arg : string | number
> : ^^^^^^^^^^^^^^^
>"string" : "string"
> : ^^^^^^^^
fn();
>fn() : string
> : ^^^^^^
>fn : () => typeof arg
> : ^^^^^^
const fn = (): typeof arg => arg;
>fn : () => typeof arg
> : ^^^^^^
>(): typeof arg => arg : () => typeof arg
> : ^^^^^^
>arg : string
> : ^^^^^^
>arg : string
> : ^^^^^^
return fn;
>fn : () => typeof arg
> : ^^^^^^
}
return undefined;
>undefined : undefined
> : ^^^^^^^^^
}
=== controlFlowFunctionLikeCircular_7.ts ===
function test(arg: string | number) {
>test : { (arg: () => string): void; (arg: () => string): void; (arg: string | number): (() => typeof arg) | undefined; (arg: string | number): (() => typeof arg) | undefined; (arg: string | number): (() => typeof arg) | undefined; (arg: string | number, whatever: any): ((arg: unknown) => arg is any) | undefined; (arg: string | number, whatever: any): (() => void) | undefined; (arg: string | number, whatever: any): (() => typeof arg) | undefined; }
> : ^^^ ^^ ^^^^^^^^^^ ^^ ^^^^^^^^^^ ^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^ ^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^ ^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^ ^^ ^^ ^^ ^^^^^ ^^ ^^^^^ ^^^^^^^^^^^^^^^^^^^ ^^ ^^ ^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^ ^^ ^^ ^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^
>arg : string | number
> : ^^^^^^^^^^^^^^^
if (typeof arg === "string") {
>typeof arg === "string" : boolean
> : ^^^^^^^
>typeof arg : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>arg : string | number
> : ^^^^^^^^^^^^^^^
>"string" : "string"
> : ^^^^^^^^
fn();
>fn() : string | number
> : ^^^^^^^^^^^^^^^
>fn : () => typeof arg
> : ^^^^^^
const fn: { (): typeof arg } = () => arg;
>fn : () => typeof arg
> : ^^^^^^
>arg : string | number
> : ^^^^^^^^^^^^^^^
>() => arg : () => string
> : ^^^^^^^^^^^^
>arg : string
> : ^^^^^^
return fn;
>fn : () => typeof arg
> : ^^^^^^
}
return undefined;
>undefined : undefined
> : ^^^^^^^^^
}
=== controlFlowFunctionLikeCircular_8.ts ===
function test(arg: string | number, whatever: any) {
>test : { (arg: () => string): void; (arg: () => string): void; (arg: string | number): (() => typeof arg) | undefined; (arg: string | number): (() => typeof arg) | undefined; (arg: string | number): (() => typeof arg) | undefined; (arg: string | number, whatever: any): ((arg: unknown) => arg is any) | undefined; (arg: string | number, whatever: any): (() => void) | undefined; (arg: string | number, whatever: any): (() => typeof arg) | undefined; }
> : ^^^ ^^ ^^^^^^^^^^ ^^ ^^^^^^^^^^ ^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^ ^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^ ^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^ ^^ ^^ ^^ ^^^^^ ^^ ^^^^^ ^^^^^^^^^^^^^^^^^^^ ^^ ^^ ^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^ ^^ ^^ ^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^
>arg : string | number
> : ^^^^^^^^^^^^^^^
>whatever : any
> : ^^^
if (typeof arg === "string") {
>typeof arg === "string" : boolean
> : ^^^^^^^
>typeof arg : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>arg : string | number
> : ^^^^^^^^^^^^^^^
>"string" : "string"
> : ^^^^^^^^
b();
>b() : boolean
> : ^^^^^^^
>b : (arg: unknown) => arg is any
> : ^ ^^ ^^^^^ ^^^
type First = typeof arg;
>First : any
> : ^^^
>arg : string
> : ^^^^^^
type Test = (arg: unknown) => arg is First;
>Test : (arg: unknown) => arg is any
> : ^ ^^ ^^^^^ ^^^
>arg : unknown
> : ^^^^^^^
const b: Test = whatever;
>b : (arg: unknown) => arg is any
> : ^ ^^ ^^^^^ ^^^
>whatever : any
> : ^^^
return b;
>b : (arg: unknown) => arg is any
> : ^ ^^ ^^^^^ ^^^
}
return undefined;
>undefined : undefined
> : ^^^^^^^^^
}
=== controlFlowFunctionLikeCircular_9.ts ===
function test(arg: string | number, whatever: any) {
>test : { (arg: () => string): void; (arg: () => string): void; (arg: string | number): (() => typeof arg) | undefined; (arg: string | number): (() => typeof arg) | undefined; (arg: string | number): (() => typeof arg) | undefined; (arg: string | number, whatever: any): ((arg: unknown) => arg is any) | undefined; (arg: string | number, whatever: any): (() => void) | undefined; (arg: string | number, whatever: any): (() => typeof arg) | undefined; }
> : ^^^ ^^ ^^^^^^^^^^ ^^ ^^^^^^^^^^ ^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^ ^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^ ^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^ ^^ ^^ ^^ ^^^^^ ^^ ^^^^^ ^^^^^^^^^^^^^^^^^^^ ^^ ^^ ^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^ ^^ ^^ ^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^
>arg : string | number
> : ^^^^^^^^^^^^^^^
>whatever : any
> : ^^^
if (typeof arg === "string") {
>typeof arg === "string" : boolean
> : ^^^^^^^
>typeof arg : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>arg : string | number
> : ^^^^^^^^^^^^^^^
>"string" : "string"
> : ^^^^^^^^
o.x();
>o.x() : void | DateConstructor
> : ^^^^^^^^^^^^^^^^^^^^^^
>o.x : (() => typeof Date) | (() => void)
> : ^^^^^^^ ^^^^^^^^^^^ ^
>o : { [k: string]: () => typeof arg; x: (() => typeof Date) | (() => void); }
> : ^^^^^^^^^^^^^^^^^^^^^ ^^^^^ ^^^
>x : (() => typeof Date) | (() => void)
> : ^^^^^^^ ^^^^^^^^^^^ ^
const o: { [k: string]: () => typeof arg; x: (() => typeof Date) | (() => void) } = whatever
>o : { [k: string]: () => typeof arg; x: (() => typeof Date) | (() => void); }
> : ^^^^^^^^^^^^^^^^^^^^^ ^^^^^ ^^^
>k : string
> : ^^^^^^
>arg : string | number
> : ^^^^^^^^^^^^^^^
>x : (() => typeof Date) | (() => void)
> : ^^^^^^^ ^^^^^^^^^^^ ^
>Date : DateConstructor
> : ^^^^^^^^^^^^^^^
>whatever : any
> : ^^^
return o.x;
>o.x : (() => typeof Date) | (() => void)
> : ^^^^^^^ ^^^^^^^^^^^ ^
>o : { [k: string]: () => typeof arg; x: (() => typeof Date) | (() => void); }
> : ^^^^^^^^^^^^^^^^^^^^^ ^^^^^ ^^^
>x : (() => typeof Date) | (() => void)
> : ^^^^^^^ ^^^^^^^^^^^ ^
}
return undefined;
>undefined : undefined
> : ^^^^^^^^^
}
=== controlFlowFunctionLikeCircular_10.ts ===
function test(arg: string | number, whatever: any) {
>test : { (arg: () => string): void; (arg: () => string): void; (arg: string | number): (() => typeof arg) | undefined; (arg: string | number): (() => typeof arg) | undefined; (arg: string | number): (() => typeof arg) | undefined; (arg: string | number, whatever: any): ((arg: unknown) => arg is any) | undefined; (arg: string | number, whatever: any): (() => void) | undefined; (arg: string | number, whatever: any): (() => typeof arg) | undefined; }
> : ^^^ ^^ ^^^^^^^^^^ ^^ ^^^^^^^^^^ ^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^ ^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^ ^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^ ^^ ^^ ^^ ^^^^^ ^^ ^^^^^ ^^^^^^^^^^^^^^^^^^^ ^^ ^^ ^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^ ^^ ^^ ^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^^
>arg : string | number
> : ^^^^^^^^^^^^^^^
>whatever : any
> : ^^^
if (typeof arg === "string") {
>typeof arg === "string" : boolean
> : ^^^^^^^
>typeof arg : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>arg : string | number
> : ^^^^^^^^^^^^^^^
>"string" : "string"
> : ^^^^^^^^
o.foo();
>o.foo() : string | number
> : ^^^^^^^^^^^^^^^
>o.foo : () => typeof arg
> : ^^^^^^
>o : { [k: string]: () => typeof arg; }
> : ^^^^^^^^^^^^^^^^^^^^^ ^^^
>foo : () => typeof arg
> : ^^^^^^
const o: { [k: string]: () => typeof arg } = whatever
>o : { [k: string]: () => typeof arg; }
> : ^^^^^^^^^^^^^^^^^^^^^ ^^^
>k : string
> : ^^^^^^
>arg : string | number
> : ^^^^^^^^^^^^^^^
>whatever : any
> : ^^^
return o.foo;
>o.foo : () => typeof arg
> : ^^^^^^
>o : { [k: string]: () => typeof arg; }
> : ^^^^^^^^^^^^^^^^^^^^^ ^^^
>foo : () => typeof arg
> : ^^^^^^
}
return undefined;
>undefined : undefined
> : ^^^^^^^^^
}

View File

@ -0,0 +1,45 @@
// @strict: true
// @noEmit: true
function test1(a: number | string) {
if (typeof a === "number") {
const fn = (arg: typeof a) => true;
return fn;
}
return;
}
test1(0)?.(100);
test1(0)?.("");
function test2(a: number | string) {
if (typeof a === "number") {
const fn: { (arg: typeof a): boolean; } = () => true;
return fn;
}
return;
}
test2(0)?.(100);
test2(0)?.("");
function test3(a: number | string) {
if (typeof a === "number") {
return (arg: typeof a) => {};
}
throw new Error("");
}
test3(1)(100);
test3(1)("");
function test4(a: number | string) {
let fn = (arg: typeof a) => {};
if (Math.random() && typeof a === "number") {
return fn;
}
throw new Error("");
}
test4(1)?.(100);
test4(1)?.("");

View File

@ -0,0 +1,84 @@
// @strict: true
// @noEmit: true
// @filename: controlFlowFunctionLikeCircular_1.ts
unionOfDifferentReturnType1(true);
const unionOfDifferentReturnType1: { (a: any): number; } | { (a: number): typeof Date; };
// @filename: controlFlowFunctionLikeCircular_2.ts
unionOfDifferentReturnType1(true);
const unionOfDifferentReturnType1 = Math.random() ? (a: any) => 1 : (a: number) => ({}) as typeof Date;
// @filename: controlFlowFunctionLikeCircular_3.ts
function test(arg: () => string) {
fn();
const fn: typeof fn = Math.random() ? arg : (): (() => arg) => {};
}
// @filename: controlFlowFunctionLikeCircular_4.ts
function test(arg: () => string) {
fn();
const fn = Math.random() ? arg : (): (() => arg) => {};
}
// @filename: controlFlowFunctionLikeCircular_5.ts
function test(arg: string | number) {
if (typeof arg === "string") {
fn();
const fn: () => typeof arg = () => arg;
return fn;
}
return undefined;
}
// @filename: controlFlowFunctionLikeCircular_6.ts
function test(arg: string | number) {
if (typeof arg === "string") {
fn();
const fn = (): typeof arg => arg;
return fn;
}
return undefined;
}
// @filename: controlFlowFunctionLikeCircular_7.ts
function test(arg: string | number) {
if (typeof arg === "string") {
fn();
const fn: { (): typeof arg } = () => arg;
return fn;
}
return undefined;
}
// @filename: controlFlowFunctionLikeCircular_8.ts
function test(arg: string | number, whatever: any) {
if (typeof arg === "string") {
b();
type First = typeof arg;
type Test = (arg: unknown) => arg is First;
const b: Test = whatever;
return b;
}
return undefined;
}
// @filename: controlFlowFunctionLikeCircular_9.ts
function test(arg: string | number, whatever: any) {
if (typeof arg === "string") {
o.x();
const o: { [k: string]: () => typeof arg; x: (() => typeof Date) | (() => void) } = whatever
return o.x;
}
return undefined;
}
// @filename: controlFlowFunctionLikeCircular_10.ts
function test(arg: string | number, whatever: any) {
if (typeof arg === "string") {
o.foo();
const o: { [k: string]: () => typeof arg } = whatever
return o.foo;
}
return undefined;
}