diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 390c843b0c968..7c7ea27e54a85 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -28708,6 +28708,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const links = getNodeLinks(node); let signature = links.effectsSignature; if (signature === undefined) { + links.effectsSignature = unknownSignature; // A call expression parented by an expression statement is a potential assertion. Other call // expressions are potential type predicate function calls. In order to avoid triggering // circularities in control flow analysis, we use getTypeOfDottedName when resolving the call diff --git a/tests/baselines/reference/controlFlowForFunctionLike1.errors.txt b/tests/baselines/reference/controlFlowForFunctionLike1.errors.txt new file mode 100644 index 0000000000000..298b0848bddd6 --- /dev/null +++ b/tests/baselines/reference/controlFlowForFunctionLike1.errors.txt @@ -0,0 +1,55 @@ +controlFlowForFunctionLike1.ts(10,12): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. +controlFlowForFunctionLike1.ts(21,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 (3 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)?.(""); + ~~ +!!! error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. + + 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)?.(""); + \ No newline at end of file diff --git a/tests/baselines/reference/controlFlowForFunctionLike1.symbols b/tests/baselines/reference/controlFlowForFunctionLike1.symbols new file mode 100644 index 0000000000000..b48b544012cdd --- /dev/null +++ b/tests/baselines/reference/controlFlowForFunctionLike1.symbols @@ -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, --, --)) +} + +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, --, --)) +} + +test4(1)?.(100); +>test4 : Symbol(test4, Decl(controlFlowForFunctionLike1.ts, 30, 13)) + +test4(1)?.(""); +>test4 : Symbol(test4, Decl(controlFlowForFunctionLike1.ts, 30, 13)) + diff --git a/tests/baselines/reference/controlFlowForFunctionLike1.types b/tests/baselines/reference/controlFlowForFunctionLike1.types new file mode 100644 index 0000000000000..3fafcb70fc1df --- /dev/null +++ b/tests/baselines/reference/controlFlowForFunctionLike1.types @@ -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 : number +> : ^^^^^^ +>a : number +> : ^^^^^^ +>() => true : () => true +> : ^^^^^^^^^^ +>true : true +> : ^^^^ + + return fn; +>fn : (arg: typeof a) => boolean +> : ^ ^^ ^^^^^ + } + return; +} + +test2(0)?.(100); +>test2(0)?.(100) : boolean | undefined +> : ^^^^^^^^^^^^^^^^^^^ +>test2(0) : ((arg: 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: 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 +> : ^ +>"" : "" +> : ^^ + diff --git a/tests/baselines/reference/controlFlowFunctionLikeCircular1.errors.txt b/tests/baselines/reference/controlFlowFunctionLikeCircular1.errors.txt new file mode 100644 index 0000000000000..0205ad08fcb07 --- /dev/null +++ b/tests/baselines/reference/controlFlowFunctionLikeCircular1.errors.txt @@ -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_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 '(() => any) | (() => void)' is not assignable to 'string' index type '() => string'. +controlFlowFunctionLikeCircular_9.ts(4,57): error TS2577: Return type annotation circularly references itself. + + +==== 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 (4 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; + type Test = (arg: unknown) => arg is First; + const b: Test = whatever; + return b; + } + return undefined; + } + +==== controlFlowFunctionLikeCircular_9.ts (5 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 '(() => any) | (() => void)' is not assignable to 'string' index type '() => string'. + ~~~~~~~~~~~ +!!! error TS2577: Return type annotation circularly references itself. + 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; + } + \ No newline at end of file diff --git a/tests/baselines/reference/controlFlowFunctionLikeCircular1.symbols b/tests/baselines/reference/controlFlowFunctionLikeCircular1.symbols new file mode 100644 index 0000000000000..6e2e6eb8024dc --- /dev/null +++ b/tests/baselines/reference/controlFlowFunctionLikeCircular1.symbols @@ -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, --, --)) + +=== 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, --, --)) + +=== 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, --, --)) +>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) +} + diff --git a/tests/baselines/reference/controlFlowFunctionLikeCircular1.types b/tests/baselines/reference/controlFlowFunctionLikeCircular1.types new file mode 100644 index 0000000000000..18d298e48f41c --- /dev/null +++ b/tests/baselines/reference/controlFlowFunctionLikeCircular1.types @@ -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 string) | undefined; (arg: string | number, whatever: any): (() => any) | 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 string) | undefined; (arg: string | number, whatever: any): (() => any) | 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 string) | undefined; (arg: string | number, whatever: any): (() => any) | 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 +> : ^^^^^^ +>arg : string +> : ^^^^^^ +>() => 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 string) | undefined; (arg: string | number, whatever: any): (() => any) | 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 string) | undefined; (arg: string | number, whatever: any): (() => any) | 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 +> : ^^^^^^ +>arg : string +> : ^^^^^^ +>() => 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 string) | undefined; (arg: string | number, whatever: any): (() => any) | 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 string +> : ^ ^^ ^^^^^ ^^^^^^ + + type First = typeof arg; +>First : string +> : ^^^^^^ +>arg : string +> : ^^^^^^ + + type Test = (arg: unknown) => arg is First; +>Test : (arg: unknown) => arg is string +> : ^ ^^ ^^^^^ ^^^^^^ +>arg : unknown +> : ^^^^^^^ + + const b: Test = whatever; +>b : (arg: unknown) => arg is string +> : ^ ^^ ^^^^^ ^^^^^^ +>whatever : any +> : ^^^ + + return b; +>b : (arg: unknown) => arg is string +> : ^ ^^ ^^^^^ ^^^^^^ + } + 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 string) | undefined; (arg: string | number, whatever: any): (() => any) | 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() : any +> : ^^^ +>o.x : (() => any) | (() => void) +> : ^^^^^^^^^^^^^^^^^^^^^ ^ +>o : { [k: string]: () => typeof arg; x: (() => typeof Date) | (() => void); } +> : ^^^^^^^^^^^^^^^^^^^^^ ^^^^^ ^^^ +>x : (() => any) | (() => 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 +> : ^^^^^^ +>x : (() => any) | (() => void) +> : ^^^^^^^^^^^^^^^^^^^^^ ^ +>Date : DateConstructor +> : ^^^^^^^^^^^^^^^ +>whatever : any +> : ^^^ + + return o.x; +>o.x : (() => any) | (() => void) +> : ^^^^^^^^^^^^^^^^^^^^^ ^ +>o : { [k: string]: () => typeof arg; x: (() => typeof Date) | (() => void); } +> : ^^^^^^^^^^^^^^^^^^^^^ ^^^^^ ^^^ +>x : (() => any) | (() => 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 string) | undefined; (arg: string | number, whatever: any): (() => any) | 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 +> : ^^^^^^ +>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 +> : ^^^^^^ +>whatever : any +> : ^^^ + + return o.foo; +>o.foo : () => typeof arg +> : ^^^^^^ +>o : { [k: string]: () => typeof arg; } +> : ^^^^^^^^^^^^^^^^^^^^^ ^^^ +>foo : () => typeof arg +> : ^^^^^^ + } + return undefined; +>undefined : undefined +> : ^^^^^^^^^ +} + diff --git a/tests/cases/compiler/controlFlowForFunctionLike1.ts b/tests/cases/compiler/controlFlowForFunctionLike1.ts new file mode 100644 index 0000000000000..9c41502bd0a00 --- /dev/null +++ b/tests/cases/compiler/controlFlowForFunctionLike1.ts @@ -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)?.(""); diff --git a/tests/cases/compiler/controlFlowFunctionLikeCircular1.ts b/tests/cases/compiler/controlFlowFunctionLikeCircular1.ts new file mode 100644 index 0000000000000..657d7f27d9a5b --- /dev/null +++ b/tests/cases/compiler/controlFlowFunctionLikeCircular1.ts @@ -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; +}