From 01670b06a5286fdc5aff16c02b8d776de8fb7261 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 12 Jul 2024 07:54:18 -0700 Subject: [PATCH] Add tests --- .../reference/deferredCallbacks.errors.txt | 259 +++++ .../baselines/reference/deferredCallbacks.js | 464 ++++++++ .../reference/deferredCallbacks.symbols | 627 ++++++++++ .../reference/deferredCallbacks.types | 1035 +++++++++++++++++ tests/cases/compiler/deferredCallbacks.ts | 238 ++++ 5 files changed, 2623 insertions(+) create mode 100644 tests/baselines/reference/deferredCallbacks.errors.txt create mode 100644 tests/baselines/reference/deferredCallbacks.js create mode 100644 tests/baselines/reference/deferredCallbacks.symbols create mode 100644 tests/baselines/reference/deferredCallbacks.types create mode 100644 tests/cases/compiler/deferredCallbacks.ts diff --git a/tests/baselines/reference/deferredCallbacks.errors.txt b/tests/baselines/reference/deferredCallbacks.errors.txt new file mode 100644 index 00000000000..c3427c4702b --- /dev/null +++ b/tests/baselines/reference/deferredCallbacks.errors.txt @@ -0,0 +1,259 @@ +deferredCallbacks.ts(119,22): error TS2869: A 'deferred' parameter must have a type that permits functions. +deferredCallbacks.ts(120,22): error TS2869: A 'deferred' parameter must have a type that permits functions. +deferredCallbacks.ts(121,22): error TS2869: A 'deferred' parameter must have a type that permits functions. +deferredCallbacks.ts(128,13): error TS2869: A 'deferred' parameter must have a type that permits functions. +deferredCallbacks.ts(129,13): error TS2869: A 'deferred' parameter must have a type that permits functions. +deferredCallbacks.ts(130,13): error TS2869: A 'deferred' parameter must have a type that permits functions. +deferredCallbacks.ts(131,14): error TS1070: 'deferred' modifier cannot appear on a type member. + + +==== deferredCallbacks.ts (7 errors) ==== + declare function immediate(cb: () => void): void; + declare function deferred1(deferred cb: () => void): void; + declare function deferred2(/** @deferred */ cb: () => void): void; + declare function deferred3(/** @deferred */ deferred cb: () => void): void; + + function f01() { + let x: string | number = "OK"; + immediate(() => { + x = 42; + }); + x; // string | number + } + + function f02() { + let x: string | number = "OK"; + deferred1(() => { + x = 42; + }); + x; // string + } + + function f03() { + let x: string | number = "OK"; + deferred2(() => { + x = 42; + }); + x; // string + } + + function f04() { + let x: string | number = "OK"; + deferred3(() => { + x = 42; + }); + x; // string + } + + // Parameter is considered deferred if one or more overloads defer that parameter + + declare function overloaded(cb: (x: T) => T): void; + declare function overloaded(cb: (x: T, y: T) => T): void; + declare function overloaded(deferred cb: (...args: any) => any): void; + + function f05() { + let x: string | number = "OK"; + overloaded(() => { + x = 42; + }); + x.length; + } + + // deferred is permitted on a rest parameter + + declare function invokeImmediate(...args: ((...args: any) => any)[]): void; + declare function invokeDeferred(deferred ...args: ((...args: any) => any)[]): void; + + function f06() { + let a = []; + a.push("abc"); + a; // string[] + invokeImmediate( + () => { + a; // string[] + a.push(42); + a; // (string | number)[] + }, + () => { + a; // string[] + a.push(true); + a; // (string | boolean)[] + } + ); + a; // (string | number | boolean)[] + } + + function f07() { + let a = []; + a.push("abc"); + a; // string[] + invokeDeferred( + () => { + a; // string[] + a.push(42); + a; // (string | number)[] + }, + () => { + a; // string[] + a.push(true); + a; // (string | boolean)[] + } + ); + a; // string[] + } + + // deferred modifier must precede public/private/protected/readonly + + class CC { + constructor(deferred public readonly x: () => void) {} + } + + // deferred requires parameter to have type that permits functions + + declare function f10(deferred f: () => void): void; + declare function f11(deferred f: Function): void; + declare function f12(deferred f: any): void; + declare function f13(deferred f: object): void; + declare function f14(deferred f: {}): void; + declare function f15(deferred f: unknown): void; + declare function f16(deferred f: T): void; + declare function f17 any>(deferred f: T): void; + declare function f18 void)>(deferred f: T): void; + + declare function f20(deferred ...funcs: Function[]): void; + declare function f21 any)[]>(deferred ...funcs: T): void; + declare function f22 void))[]>(deferred ...funcs: T): void; + declare function f23 void)[]>(deferred ...funcs: T): void; + declare function f24 void)[]>(deferred ...funcs: T | string[]): void; + + declare function f30(deferred f: { foo(): void }): void; + ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2869: A 'deferred' parameter must have a type that permits functions. + declare function f31(deferred f: number): void; + ~~~~~~~~~~~~~~~~~~ +!!! error TS2869: A 'deferred' parameter must have a type that permits functions. + declare function f32(deferred ...funcs: number[]): void; + ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2869: A 'deferred' parameter must have a type that permits functions. + + type T10 = (deferred f: () => void) => void; + type T11 = (deferred f: { (): void }) => void; + type T12 = (deferred f: Function) => void; + type T13 = (deferred f: any) => void; + + type T20 = (deferred f: { foo(): void }) => void; + ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2869: A 'deferred' parameter must have a type that permits functions. + type T21 = (deferred f: number) => void; + ~~~~~~~~~~~~~~~~~~ +!!! error TS2869: A 'deferred' parameter must have a type that permits functions. + type T22 = (deferred ...funcs: number[]) => void; + ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2869: A 'deferred' parameter must have a type that permits functions. + type T23 = { deferred x: () => void }; + ~~~~~~~~ +!!! error TS1070: 'deferred' modifier cannot appear on a type member. + + // deferred modifier is not captured in argument list tuples + + declare function doStuff(deferred f: () => void): void; + + declare function recreate(f: (...args: A) => R): (...args: A) => R; + declare function recreateDeferred1(f: (deferred ...args: A) => R): (...args: A) => R; + declare function recreateDeferred2(f: (...args: A) => R): (deferred ...args: A) => R; + + function ff1() { + let x: string | number; + x = 123; + doStuff(() => { + x = "hi"; + }); + x; // number + } + + function ff2() { + let y: string | number; + y = 123; + recreate(doStuff)(() => { + y = "hi"; + }); + y; // string | number + } + + function ff3() { + let z: string | number; + z = 123; + recreateDeferred1(doStuff)(() => { + z = "hi"; + }); + z; // string | number + } + + function ff4() { + let z: string | number; + z = 123; + recreateDeferred2(doStuff)(() => { + z = "hi"; + }); + z; // number + } + + // https://github.com/microsoft/TypeScript/issues/11498 + + declare function mystery(cb: () => void): void; + + function fx1() { + let x: string | number = "OK"; + x; // string + mystery(() => { + x = 10; + }); + x; // string | number + if (x === 10) {} + } + + // https://github.com/microsoft/TypeScript/issues/15380 + + class Foo { + public bar: string = ""; + } + + function fx2() { + let foo: Foo | null = null; + [1].forEach((item) => { + foo = new Foo(); + }); + if (foo) { + foo.bar; + } + } + + // https://github.com/microsoft/TypeScript/issues/57880 + + const call = (f: () => void) => f(); + + const fx3 = () => { + let a: undefined | number = undefined; + call(() => { a = 1; }); + if (a !== undefined) { + a.toString(); + } + }; + + // https://github.com/microsoft/TypeScript/issues/58291 + + async function execute(onError: (_err: Error | undefined) => void) { + onError(new Error("a")); + } + + async function run() { + let result: boolean = true; + await execute(() => { + result = false; + }); + if (result === false) { + console.log("error"); + } + return result; + } + \ No newline at end of file diff --git a/tests/baselines/reference/deferredCallbacks.js b/tests/baselines/reference/deferredCallbacks.js new file mode 100644 index 00000000000..da1accd10bb --- /dev/null +++ b/tests/baselines/reference/deferredCallbacks.js @@ -0,0 +1,464 @@ +//// [tests/cases/compiler/deferredCallbacks.ts] //// + +//// [deferredCallbacks.ts] +declare function immediate(cb: () => void): void; +declare function deferred1(deferred cb: () => void): void; +declare function deferred2(/** @deferred */ cb: () => void): void; +declare function deferred3(/** @deferred */ deferred cb: () => void): void; + +function f01() { + let x: string | number = "OK"; + immediate(() => { + x = 42; + }); + x; // string | number +} + +function f02() { + let x: string | number = "OK"; + deferred1(() => { + x = 42; + }); + x; // string +} + +function f03() { + let x: string | number = "OK"; + deferred2(() => { + x = 42; + }); + x; // string +} + +function f04() { + let x: string | number = "OK"; + deferred3(() => { + x = 42; + }); + x; // string +} + +// Parameter is considered deferred if one or more overloads defer that parameter + +declare function overloaded(cb: (x: T) => T): void; +declare function overloaded(cb: (x: T, y: T) => T): void; +declare function overloaded(deferred cb: (...args: any) => any): void; + +function f05() { + let x: string | number = "OK"; + overloaded(() => { + x = 42; + }); + x.length; +} + +// deferred is permitted on a rest parameter + +declare function invokeImmediate(...args: ((...args: any) => any)[]): void; +declare function invokeDeferred(deferred ...args: ((...args: any) => any)[]): void; + +function f06() { + let a = []; + a.push("abc"); + a; // string[] + invokeImmediate( + () => { + a; // string[] + a.push(42); + a; // (string | number)[] + }, + () => { + a; // string[] + a.push(true); + a; // (string | boolean)[] + } + ); + a; // (string | number | boolean)[] +} + +function f07() { + let a = []; + a.push("abc"); + a; // string[] + invokeDeferred( + () => { + a; // string[] + a.push(42); + a; // (string | number)[] + }, + () => { + a; // string[] + a.push(true); + a; // (string | boolean)[] + } + ); + a; // string[] +} + +// deferred modifier must precede public/private/protected/readonly + +class CC { + constructor(deferred public readonly x: () => void) {} +} + +// deferred requires parameter to have type that permits functions + +declare function f10(deferred f: () => void): void; +declare function f11(deferred f: Function): void; +declare function f12(deferred f: any): void; +declare function f13(deferred f: object): void; +declare function f14(deferred f: {}): void; +declare function f15(deferred f: unknown): void; +declare function f16(deferred f: T): void; +declare function f17 any>(deferred f: T): void; +declare function f18 void)>(deferred f: T): void; + +declare function f20(deferred ...funcs: Function[]): void; +declare function f21 any)[]>(deferred ...funcs: T): void; +declare function f22 void))[]>(deferred ...funcs: T): void; +declare function f23 void)[]>(deferred ...funcs: T): void; +declare function f24 void)[]>(deferred ...funcs: T | string[]): void; + +declare function f30(deferred f: { foo(): void }): void; +declare function f31(deferred f: number): void; +declare function f32(deferred ...funcs: number[]): void; + +type T10 = (deferred f: () => void) => void; +type T11 = (deferred f: { (): void }) => void; +type T12 = (deferred f: Function) => void; +type T13 = (deferred f: any) => void; + +type T20 = (deferred f: { foo(): void }) => void; +type T21 = (deferred f: number) => void; +type T22 = (deferred ...funcs: number[]) => void; +type T23 = { deferred x: () => void }; + +// deferred modifier is not captured in argument list tuples + +declare function doStuff(deferred f: () => void): void; + +declare function recreate(f: (...args: A) => R): (...args: A) => R; +declare function recreateDeferred1(f: (deferred ...args: A) => R): (...args: A) => R; +declare function recreateDeferred2(f: (...args: A) => R): (deferred ...args: A) => R; + +function ff1() { + let x: string | number; + x = 123; + doStuff(() => { + x = "hi"; + }); + x; // number +} + +function ff2() { + let y: string | number; + y = 123; + recreate(doStuff)(() => { + y = "hi"; + }); + y; // string | number +} + +function ff3() { + let z: string | number; + z = 123; + recreateDeferred1(doStuff)(() => { + z = "hi"; + }); + z; // string | number +} + +function ff4() { + let z: string | number; + z = 123; + recreateDeferred2(doStuff)(() => { + z = "hi"; + }); + z; // number +} + +// https://github.com/microsoft/TypeScript/issues/11498 + +declare function mystery(cb: () => void): void; + +function fx1() { + let x: string | number = "OK"; + x; // string + mystery(() => { + x = 10; + }); + x; // string | number + if (x === 10) {} +} + +// https://github.com/microsoft/TypeScript/issues/15380 + +class Foo { + public bar: string = ""; +} + +function fx2() { + let foo: Foo | null = null; + [1].forEach((item) => { + foo = new Foo(); + }); + if (foo) { + foo.bar; + } +} + +// https://github.com/microsoft/TypeScript/issues/57880 + +const call = (f: () => void) => f(); + +const fx3 = () => { + let a: undefined | number = undefined; + call(() => { a = 1; }); + if (a !== undefined) { + a.toString(); + } +}; + +// https://github.com/microsoft/TypeScript/issues/58291 + +async function execute(onError: (_err: Error | undefined) => void) { + onError(new Error("a")); +} + +async function run() { + let result: boolean = true; + await execute(() => { + result = false; + }); + if (result === false) { + console.log("error"); + } + return result; +} + + +//// [deferredCallbacks.js] +"use strict"; +function f01() { + let x = "OK"; + immediate(() => { + x = 42; + }); + x; // string | number +} +function f02() { + let x = "OK"; + deferred1(() => { + x = 42; + }); + x; // string +} +function f03() { + let x = "OK"; + deferred2(() => { + x = 42; + }); + x; // string +} +function f04() { + let x = "OK"; + deferred3(() => { + x = 42; + }); + x; // string +} +function f05() { + let x = "OK"; + overloaded(() => { + x = 42; + }); + x.length; +} +function f06() { + let a = []; + a.push("abc"); + a; // string[] + invokeImmediate(() => { + a; // string[] + a.push(42); + a; // (string | number)[] + }, () => { + a; // string[] + a.push(true); + a; // (string | boolean)[] + }); + a; // (string | number | boolean)[] +} +function f07() { + let a = []; + a.push("abc"); + a; // string[] + invokeDeferred(() => { + a; // string[] + a.push(42); + a; // (string | number)[] + }, () => { + a; // string[] + a.push(true); + a; // (string | boolean)[] + }); + a; // string[] +} +// deferred modifier must precede public/private/protected/readonly +class CC { + x; + constructor(x) { + this.x = x; + } +} +function ff1() { + let x; + x = 123; + doStuff(() => { + x = "hi"; + }); + x; // number +} +function ff2() { + let y; + y = 123; + recreate(doStuff)(() => { + y = "hi"; + }); + y; // string | number +} +function ff3() { + let z; + z = 123; + recreateDeferred1(doStuff)(() => { + z = "hi"; + }); + z; // string | number +} +function ff4() { + let z; + z = 123; + recreateDeferred2(doStuff)(() => { + z = "hi"; + }); + z; // number +} +function fx1() { + let x = "OK"; + x; // string + mystery(() => { + x = 10; + }); + x; // string | number + if (x === 10) { } +} +// https://github.com/microsoft/TypeScript/issues/15380 +class Foo { + bar = ""; +} +function fx2() { + let foo = null; + [1].forEach((item) => { + foo = new Foo(); + }); + if (foo) { + foo.bar; + } +} +// https://github.com/microsoft/TypeScript/issues/57880 +const call = (f) => f(); +const fx3 = () => { + let a = undefined; + call(() => { a = 1; }); + if (a !== undefined) { + a.toString(); + } +}; +// https://github.com/microsoft/TypeScript/issues/58291 +async function execute(onError) { + onError(new Error("a")); +} +async function run() { + let result = true; + await execute(() => { + result = false; + }); + if (result === false) { + console.log("error"); + } + return result; +} + + +//// [deferredCallbacks.d.ts] +declare function immediate(cb: () => void): void; +declare function deferred1(deferred cb: () => void): void; +declare function deferred2(/** @deferred */ cb: () => void): void; +declare function deferred3(/** @deferred */ deferred cb: () => void): void; +declare function f01(): void; +declare function f02(): void; +declare function f03(): void; +declare function f04(): void; +declare function overloaded(cb: (x: T) => T): void; +declare function overloaded(cb: (x: T, y: T) => T): void; +declare function overloaded(deferred cb: (...args: any) => any): void; +declare function f05(): void; +declare function invokeImmediate(...args: ((...args: any) => any)[]): void; +declare function invokeDeferred(deferred ...args: ((...args: any) => any)[]): void; +declare function f06(): void; +declare function f07(): void; +declare class CC { + deferred readonly x: () => void; + constructor(x: () => void); +} +declare function f10(deferred f: () => void): void; +declare function f11(deferred f: Function): void; +declare function f12(deferred f: any): void; +declare function f13(deferred f: object): void; +declare function f14(deferred f: {}): void; +declare function f15(deferred f: unknown): void; +declare function f16(deferred f: T): void; +declare function f17 any>(deferred f: T): void; +declare function f18 void)>(deferred f: T): void; +declare function f20(deferred ...funcs: Function[]): void; +declare function f21 any)[]>(deferred ...funcs: T): void; +declare function f22 void))[]>(deferred ...funcs: T): void; +declare function f23 void)[]>(deferred ...funcs: T): void; +declare function f24 void)[]>(deferred ...funcs: T | string[]): void; +declare function f30(deferred f: { + foo(): void; +}): void; +declare function f31(deferred f: number): void; +declare function f32(deferred ...funcs: number[]): void; +type T10 = (deferred f: () => void) => void; +type T11 = (deferred f: { + (): void; +}) => void; +type T12 = (deferred f: Function) => void; +type T13 = (deferred f: any) => void; +type T20 = (deferred f: { + foo(): void; +}) => void; +type T21 = (deferred f: number) => void; +type T22 = (deferred ...funcs: number[]) => void; +type T23 = { + deferred x: () => void; +}; +declare function doStuff(deferred f: () => void): void; +declare function recreate(f: (...args: A) => R): (...args: A) => R; +declare function recreateDeferred1(f: (deferred ...args: A) => R): (...args: A) => R; +declare function recreateDeferred2(f: (...args: A) => R): (deferred ...args: A) => R; +declare function ff1(): void; +declare function ff2(): void; +declare function ff3(): void; +declare function ff4(): void; +declare function mystery(cb: () => void): void; +declare function fx1(): void; +declare class Foo { + bar: string; +} +declare function fx2(): void; +declare const call: (f: () => void) => void; +declare const fx3: () => void; +declare function execute(onError: (_err: Error | undefined) => void): Promise; +declare function run(): Promise; diff --git a/tests/baselines/reference/deferredCallbacks.symbols b/tests/baselines/reference/deferredCallbacks.symbols new file mode 100644 index 00000000000..1d8162916b5 --- /dev/null +++ b/tests/baselines/reference/deferredCallbacks.symbols @@ -0,0 +1,627 @@ +//// [tests/cases/compiler/deferredCallbacks.ts] //// + +=== deferredCallbacks.ts === +declare function immediate(cb: () => void): void; +>immediate : Symbol(immediate, Decl(deferredCallbacks.ts, 0, 0)) +>cb : Symbol(cb, Decl(deferredCallbacks.ts, 0, 27)) + +declare function deferred1(deferred cb: () => void): void; +>deferred1 : Symbol(deferred1, Decl(deferredCallbacks.ts, 0, 49)) +>cb : Symbol(cb, Decl(deferredCallbacks.ts, 1, 27)) + +declare function deferred2(/** @deferred */ cb: () => void): void; +>deferred2 : Symbol(deferred2, Decl(deferredCallbacks.ts, 1, 58)) +>cb : Symbol(cb, Decl(deferredCallbacks.ts, 2, 27)) + +declare function deferred3(/** @deferred */ deferred cb: () => void): void; +>deferred3 : Symbol(deferred3, Decl(deferredCallbacks.ts, 2, 66)) +>cb : Symbol(cb, Decl(deferredCallbacks.ts, 3, 27)) + +function f01() { +>f01 : Symbol(f01, Decl(deferredCallbacks.ts, 3, 75)) + + let x: string | number = "OK"; +>x : Symbol(x, Decl(deferredCallbacks.ts, 6, 7)) + + immediate(() => { +>immediate : Symbol(immediate, Decl(deferredCallbacks.ts, 0, 0)) + + x = 42; +>x : Symbol(x, Decl(deferredCallbacks.ts, 6, 7)) + + }); + x; // string | number +>x : Symbol(x, Decl(deferredCallbacks.ts, 6, 7)) +} + +function f02() { +>f02 : Symbol(f02, Decl(deferredCallbacks.ts, 11, 1)) + + let x: string | number = "OK"; +>x : Symbol(x, Decl(deferredCallbacks.ts, 14, 7)) + + deferred1(() => { +>deferred1 : Symbol(deferred1, Decl(deferredCallbacks.ts, 0, 49)) + + x = 42; +>x : Symbol(x, Decl(deferredCallbacks.ts, 14, 7)) + + }); + x; // string +>x : Symbol(x, Decl(deferredCallbacks.ts, 14, 7)) +} + +function f03() { +>f03 : Symbol(f03, Decl(deferredCallbacks.ts, 19, 1)) + + let x: string | number = "OK"; +>x : Symbol(x, Decl(deferredCallbacks.ts, 22, 7)) + + deferred2(() => { +>deferred2 : Symbol(deferred2, Decl(deferredCallbacks.ts, 1, 58)) + + x = 42; +>x : Symbol(x, Decl(deferredCallbacks.ts, 22, 7)) + + }); + x; // string +>x : Symbol(x, Decl(deferredCallbacks.ts, 22, 7)) +} + +function f04() { +>f04 : Symbol(f04, Decl(deferredCallbacks.ts, 27, 1)) + + let x: string | number = "OK"; +>x : Symbol(x, Decl(deferredCallbacks.ts, 30, 7)) + + deferred3(() => { +>deferred3 : Symbol(deferred3, Decl(deferredCallbacks.ts, 2, 66)) + + x = 42; +>x : Symbol(x, Decl(deferredCallbacks.ts, 30, 7)) + + }); + x; // string +>x : Symbol(x, Decl(deferredCallbacks.ts, 30, 7)) +} + +// Parameter is considered deferred if one or more overloads defer that parameter + +declare function overloaded(cb: (x: T) => T): void; +>overloaded : Symbol(overloaded, Decl(deferredCallbacks.ts, 35, 1), Decl(deferredCallbacks.ts, 39, 54), Decl(deferredCallbacks.ts, 40, 60)) +>T : Symbol(T, Decl(deferredCallbacks.ts, 39, 28)) +>cb : Symbol(cb, Decl(deferredCallbacks.ts, 39, 31)) +>x : Symbol(x, Decl(deferredCallbacks.ts, 39, 36)) +>T : Symbol(T, Decl(deferredCallbacks.ts, 39, 28)) +>T : Symbol(T, Decl(deferredCallbacks.ts, 39, 28)) + +declare function overloaded(cb: (x: T, y: T) => T): void; +>overloaded : Symbol(overloaded, Decl(deferredCallbacks.ts, 35, 1), Decl(deferredCallbacks.ts, 39, 54), Decl(deferredCallbacks.ts, 40, 60)) +>T : Symbol(T, Decl(deferredCallbacks.ts, 40, 28)) +>cb : Symbol(cb, Decl(deferredCallbacks.ts, 40, 31)) +>x : Symbol(x, Decl(deferredCallbacks.ts, 40, 36)) +>T : Symbol(T, Decl(deferredCallbacks.ts, 40, 28)) +>y : Symbol(y, Decl(deferredCallbacks.ts, 40, 41)) +>T : Symbol(T, Decl(deferredCallbacks.ts, 40, 28)) +>T : Symbol(T, Decl(deferredCallbacks.ts, 40, 28)) + +declare function overloaded(deferred cb: (...args: any) => any): void; +>overloaded : Symbol(overloaded, Decl(deferredCallbacks.ts, 35, 1), Decl(deferredCallbacks.ts, 39, 54), Decl(deferredCallbacks.ts, 40, 60)) +>cb : Symbol(cb, Decl(deferredCallbacks.ts, 41, 28)) +>args : Symbol(args, Decl(deferredCallbacks.ts, 41, 42)) + +function f05() { +>f05 : Symbol(f05, Decl(deferredCallbacks.ts, 41, 70)) + + let x: string | number = "OK"; +>x : Symbol(x, Decl(deferredCallbacks.ts, 44, 7)) + + overloaded(() => { +>overloaded : Symbol(overloaded, Decl(deferredCallbacks.ts, 35, 1), Decl(deferredCallbacks.ts, 39, 54), Decl(deferredCallbacks.ts, 40, 60)) + + x = 42; +>x : Symbol(x, Decl(deferredCallbacks.ts, 44, 7)) + + }); + x.length; +>x.length : Symbol(String.length, Decl(lib.es5.d.ts, --, --)) +>x : Symbol(x, Decl(deferredCallbacks.ts, 44, 7)) +>length : Symbol(String.length, Decl(lib.es5.d.ts, --, --)) +} + +// deferred is permitted on a rest parameter + +declare function invokeImmediate(...args: ((...args: any) => any)[]): void; +>invokeImmediate : Symbol(invokeImmediate, Decl(deferredCallbacks.ts, 49, 1)) +>args : Symbol(args, Decl(deferredCallbacks.ts, 53, 33)) +>args : Symbol(args, Decl(deferredCallbacks.ts, 53, 44)) + +declare function invokeDeferred(deferred ...args: ((...args: any) => any)[]): void; +>invokeDeferred : Symbol(invokeDeferred, Decl(deferredCallbacks.ts, 53, 75)) +>args : Symbol(args, Decl(deferredCallbacks.ts, 54, 32)) +>args : Symbol(args, Decl(deferredCallbacks.ts, 54, 52)) + +function f06() { +>f06 : Symbol(f06, Decl(deferredCallbacks.ts, 54, 83)) + + let a = []; +>a : Symbol(a, Decl(deferredCallbacks.ts, 57, 7)) + + a.push("abc"); +>a.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>a : Symbol(a, Decl(deferredCallbacks.ts, 57, 7)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) + + a; // string[] +>a : Symbol(a, Decl(deferredCallbacks.ts, 57, 7)) + + invokeImmediate( +>invokeImmediate : Symbol(invokeImmediate, Decl(deferredCallbacks.ts, 49, 1)) + + () => { + a; // string[] +>a : Symbol(a, Decl(deferredCallbacks.ts, 57, 7)) + + a.push(42); +>a.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>a : Symbol(a, Decl(deferredCallbacks.ts, 57, 7)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) + + a; // (string | number)[] +>a : Symbol(a, Decl(deferredCallbacks.ts, 57, 7)) + + }, + () => { + a; // string[] +>a : Symbol(a, Decl(deferredCallbacks.ts, 57, 7)) + + a.push(true); +>a.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>a : Symbol(a, Decl(deferredCallbacks.ts, 57, 7)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) + + a; // (string | boolean)[] +>a : Symbol(a, Decl(deferredCallbacks.ts, 57, 7)) + } + ); + a; // (string | number | boolean)[] +>a : Symbol(a, Decl(deferredCallbacks.ts, 57, 7)) +} + +function f07() { +>f07 : Symbol(f07, Decl(deferredCallbacks.ts, 73, 1)) + + let a = []; +>a : Symbol(a, Decl(deferredCallbacks.ts, 76, 7)) + + a.push("abc"); +>a.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>a : Symbol(a, Decl(deferredCallbacks.ts, 76, 7)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) + + a; // string[] +>a : Symbol(a, Decl(deferredCallbacks.ts, 76, 7)) + + invokeDeferred( +>invokeDeferred : Symbol(invokeDeferred, Decl(deferredCallbacks.ts, 53, 75)) + + () => { + a; // string[] +>a : Symbol(a, Decl(deferredCallbacks.ts, 76, 7)) + + a.push(42); +>a.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>a : Symbol(a, Decl(deferredCallbacks.ts, 76, 7)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) + + a; // (string | number)[] +>a : Symbol(a, Decl(deferredCallbacks.ts, 76, 7)) + + }, + () => { + a; // string[] +>a : Symbol(a, Decl(deferredCallbacks.ts, 76, 7)) + + a.push(true); +>a.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>a : Symbol(a, Decl(deferredCallbacks.ts, 76, 7)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) + + a; // (string | boolean)[] +>a : Symbol(a, Decl(deferredCallbacks.ts, 76, 7)) + } + ); + a; // string[] +>a : Symbol(a, Decl(deferredCallbacks.ts, 76, 7)) +} + +// deferred modifier must precede public/private/protected/readonly + +class CC { +>CC : Symbol(CC, Decl(deferredCallbacks.ts, 92, 1)) + + constructor(deferred public readonly x: () => void) {} +>x : Symbol(CC.x, Decl(deferredCallbacks.ts, 97, 16)) +} + +// deferred requires parameter to have type that permits functions + +declare function f10(deferred f: () => void): void; +>f10 : Symbol(f10, Decl(deferredCallbacks.ts, 98, 1)) +>f : Symbol(f, Decl(deferredCallbacks.ts, 102, 21)) + +declare function f11(deferred f: Function): void; +>f11 : Symbol(f11, Decl(deferredCallbacks.ts, 102, 51)) +>f : Symbol(f, Decl(deferredCallbacks.ts, 103, 21)) +>Function : Symbol(Function, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.esnext.decorators.d.ts, --, --)) + +declare function f12(deferred f: any): void; +>f12 : Symbol(f12, Decl(deferredCallbacks.ts, 103, 49)) +>f : Symbol(f, Decl(deferredCallbacks.ts, 104, 21)) + +declare function f13(deferred f: object): void; +>f13 : Symbol(f13, Decl(deferredCallbacks.ts, 104, 44)) +>f : Symbol(f, Decl(deferredCallbacks.ts, 105, 21)) + +declare function f14(deferred f: {}): void; +>f14 : Symbol(f14, Decl(deferredCallbacks.ts, 105, 47)) +>f : Symbol(f, Decl(deferredCallbacks.ts, 106, 21)) + +declare function f15(deferred f: unknown): void; +>f15 : Symbol(f15, Decl(deferredCallbacks.ts, 106, 43)) +>f : Symbol(f, Decl(deferredCallbacks.ts, 107, 21)) + +declare function f16(deferred f: T): void; +>f16 : Symbol(f16, Decl(deferredCallbacks.ts, 107, 48)) +>T : Symbol(T, Decl(deferredCallbacks.ts, 108, 21)) +>Function : Symbol(Function, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.esnext.decorators.d.ts, --, --)) +>f : Symbol(f, Decl(deferredCallbacks.ts, 108, 41)) +>T : Symbol(T, Decl(deferredCallbacks.ts, 108, 21)) + +declare function f17 any>(deferred f: T): void; +>f17 : Symbol(f17, Decl(deferredCallbacks.ts, 108, 62)) +>T : Symbol(T, Decl(deferredCallbacks.ts, 109, 21)) +>args : Symbol(args, Decl(deferredCallbacks.ts, 109, 32)) +>f : Symbol(f, Decl(deferredCallbacks.ts, 109, 54)) +>T : Symbol(T, Decl(deferredCallbacks.ts, 109, 21)) + +declare function f18 void)>(deferred f: T): void; +>f18 : Symbol(f18, Decl(deferredCallbacks.ts, 109, 75)) +>T : Symbol(T, Decl(deferredCallbacks.ts, 110, 21)) +>f : Symbol(f, Decl(deferredCallbacks.ts, 110, 54)) +>T : Symbol(T, Decl(deferredCallbacks.ts, 110, 21)) + +declare function f20(deferred ...funcs: Function[]): void; +>f20 : Symbol(f20, Decl(deferredCallbacks.ts, 110, 75)) +>funcs : Symbol(funcs, Decl(deferredCallbacks.ts, 112, 21)) +>Function : Symbol(Function, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.esnext.decorators.d.ts, --, --)) + +declare function f21 any)[]>(deferred ...funcs: T): void; +>f21 : Symbol(f21, Decl(deferredCallbacks.ts, 112, 58)) +>T : Symbol(T, Decl(deferredCallbacks.ts, 113, 21)) +>args : Symbol(args, Decl(deferredCallbacks.ts, 113, 33)) +>funcs : Symbol(funcs, Decl(deferredCallbacks.ts, 113, 58)) +>T : Symbol(T, Decl(deferredCallbacks.ts, 113, 21)) + +declare function f22 void))[]>(deferred ...funcs: T): void; +>f22 : Symbol(f22, Decl(deferredCallbacks.ts, 113, 86)) +>T : Symbol(T, Decl(deferredCallbacks.ts, 114, 21)) +>funcs : Symbol(funcs, Decl(deferredCallbacks.ts, 114, 58)) +>T : Symbol(T, Decl(deferredCallbacks.ts, 114, 21)) + +declare function f23 void)[]>(deferred ...funcs: T): void; +>f23 : Symbol(f23, Decl(deferredCallbacks.ts, 114, 86)) +>T : Symbol(T, Decl(deferredCallbacks.ts, 115, 21)) +>funcs : Symbol(funcs, Decl(deferredCallbacks.ts, 115, 58)) +>T : Symbol(T, Decl(deferredCallbacks.ts, 115, 21)) + +declare function f24 void)[]>(deferred ...funcs: T | string[]): void; +>f24 : Symbol(f24, Decl(deferredCallbacks.ts, 115, 86)) +>T : Symbol(T, Decl(deferredCallbacks.ts, 116, 21)) +>funcs : Symbol(funcs, Decl(deferredCallbacks.ts, 116, 47)) +>T : Symbol(T, Decl(deferredCallbacks.ts, 116, 21)) + +declare function f30(deferred f: { foo(): void }): void; +>f30 : Symbol(f30, Decl(deferredCallbacks.ts, 116, 86)) +>f : Symbol(f, Decl(deferredCallbacks.ts, 118, 21)) +>foo : Symbol(foo, Decl(deferredCallbacks.ts, 118, 34)) + +declare function f31(deferred f: number): void; +>f31 : Symbol(f31, Decl(deferredCallbacks.ts, 118, 56)) +>f : Symbol(f, Decl(deferredCallbacks.ts, 119, 21)) + +declare function f32(deferred ...funcs: number[]): void; +>f32 : Symbol(f32, Decl(deferredCallbacks.ts, 119, 47)) +>funcs : Symbol(funcs, Decl(deferredCallbacks.ts, 120, 21)) + +type T10 = (deferred f: () => void) => void; +>T10 : Symbol(T10, Decl(deferredCallbacks.ts, 120, 56)) +>f : Symbol(f, Decl(deferredCallbacks.ts, 122, 12)) + +type T11 = (deferred f: { (): void }) => void; +>T11 : Symbol(T11, Decl(deferredCallbacks.ts, 122, 44)) +>f : Symbol(f, Decl(deferredCallbacks.ts, 123, 12)) + +type T12 = (deferred f: Function) => void; +>T12 : Symbol(T12, Decl(deferredCallbacks.ts, 123, 46)) +>f : Symbol(f, Decl(deferredCallbacks.ts, 124, 12)) +>Function : Symbol(Function, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.esnext.decorators.d.ts, --, --)) + +type T13 = (deferred f: any) => void; +>T13 : Symbol(T13, Decl(deferredCallbacks.ts, 124, 42)) +>f : Symbol(f, Decl(deferredCallbacks.ts, 125, 12)) + +type T20 = (deferred f: { foo(): void }) => void; +>T20 : Symbol(T20, Decl(deferredCallbacks.ts, 125, 37)) +>f : Symbol(f, Decl(deferredCallbacks.ts, 127, 12)) +>foo : Symbol(foo, Decl(deferredCallbacks.ts, 127, 25)) + +type T21 = (deferred f: number) => void; +>T21 : Symbol(T21, Decl(deferredCallbacks.ts, 127, 49)) +>f : Symbol(f, Decl(deferredCallbacks.ts, 128, 12)) + +type T22 = (deferred ...funcs: number[]) => void; +>T22 : Symbol(T22, Decl(deferredCallbacks.ts, 128, 40)) +>funcs : Symbol(funcs, Decl(deferredCallbacks.ts, 129, 12)) + +type T23 = { deferred x: () => void }; +>T23 : Symbol(T23, Decl(deferredCallbacks.ts, 129, 49)) +>x : Symbol(x, Decl(deferredCallbacks.ts, 130, 12)) + +// deferred modifier is not captured in argument list tuples + +declare function doStuff(deferred f: () => void): void; +>doStuff : Symbol(doStuff, Decl(deferredCallbacks.ts, 130, 38)) +>f : Symbol(f, Decl(deferredCallbacks.ts, 134, 25)) + +declare function recreate(f: (...args: A) => R): (...args: A) => R; +>recreate : Symbol(recreate, Decl(deferredCallbacks.ts, 134, 55)) +>A : Symbol(A, Decl(deferredCallbacks.ts, 136, 26)) +>R : Symbol(R, Decl(deferredCallbacks.ts, 136, 46)) +>f : Symbol(f, Decl(deferredCallbacks.ts, 136, 50)) +>args : Symbol(args, Decl(deferredCallbacks.ts, 136, 54)) +>A : Symbol(A, Decl(deferredCallbacks.ts, 136, 26)) +>R : Symbol(R, Decl(deferredCallbacks.ts, 136, 46)) +>args : Symbol(args, Decl(deferredCallbacks.ts, 136, 74)) +>A : Symbol(A, Decl(deferredCallbacks.ts, 136, 26)) +>R : Symbol(R, Decl(deferredCallbacks.ts, 136, 46)) + +declare function recreateDeferred1(f: (deferred ...args: A) => R): (...args: A) => R; +>recreateDeferred1 : Symbol(recreateDeferred1, Decl(deferredCallbacks.ts, 136, 91)) +>A : Symbol(A, Decl(deferredCallbacks.ts, 137, 35)) +>R : Symbol(R, Decl(deferredCallbacks.ts, 137, 55)) +>f : Symbol(f, Decl(deferredCallbacks.ts, 137, 59)) +>args : Symbol(args, Decl(deferredCallbacks.ts, 137, 63)) +>A : Symbol(A, Decl(deferredCallbacks.ts, 137, 35)) +>R : Symbol(R, Decl(deferredCallbacks.ts, 137, 55)) +>args : Symbol(args, Decl(deferredCallbacks.ts, 137, 92)) +>A : Symbol(A, Decl(deferredCallbacks.ts, 137, 35)) +>R : Symbol(R, Decl(deferredCallbacks.ts, 137, 55)) + +declare function recreateDeferred2(f: (...args: A) => R): (deferred ...args: A) => R; +>recreateDeferred2 : Symbol(recreateDeferred2, Decl(deferredCallbacks.ts, 137, 109)) +>A : Symbol(A, Decl(deferredCallbacks.ts, 138, 35)) +>R : Symbol(R, Decl(deferredCallbacks.ts, 138, 55)) +>f : Symbol(f, Decl(deferredCallbacks.ts, 138, 59)) +>args : Symbol(args, Decl(deferredCallbacks.ts, 138, 63)) +>A : Symbol(A, Decl(deferredCallbacks.ts, 138, 35)) +>R : Symbol(R, Decl(deferredCallbacks.ts, 138, 55)) +>args : Symbol(args, Decl(deferredCallbacks.ts, 138, 83)) +>A : Symbol(A, Decl(deferredCallbacks.ts, 138, 35)) +>R : Symbol(R, Decl(deferredCallbacks.ts, 138, 55)) + +function ff1() { +>ff1 : Symbol(ff1, Decl(deferredCallbacks.ts, 138, 109)) + + let x: string | number; +>x : Symbol(x, Decl(deferredCallbacks.ts, 141, 7)) + + x = 123; +>x : Symbol(x, Decl(deferredCallbacks.ts, 141, 7)) + + doStuff(() => { +>doStuff : Symbol(doStuff, Decl(deferredCallbacks.ts, 130, 38)) + + x = "hi"; +>x : Symbol(x, Decl(deferredCallbacks.ts, 141, 7)) + + }); + x; // number +>x : Symbol(x, Decl(deferredCallbacks.ts, 141, 7)) +} + +function ff2() { +>ff2 : Symbol(ff2, Decl(deferredCallbacks.ts, 147, 1)) + + let y: string | number; +>y : Symbol(y, Decl(deferredCallbacks.ts, 150, 7)) + + y = 123; +>y : Symbol(y, Decl(deferredCallbacks.ts, 150, 7)) + + recreate(doStuff)(() => { +>recreate : Symbol(recreate, Decl(deferredCallbacks.ts, 134, 55)) +>doStuff : Symbol(doStuff, Decl(deferredCallbacks.ts, 130, 38)) + + y = "hi"; +>y : Symbol(y, Decl(deferredCallbacks.ts, 150, 7)) + + }); + y; // string | number +>y : Symbol(y, Decl(deferredCallbacks.ts, 150, 7)) +} + +function ff3() { +>ff3 : Symbol(ff3, Decl(deferredCallbacks.ts, 156, 1)) + + let z: string | number; +>z : Symbol(z, Decl(deferredCallbacks.ts, 159, 7)) + + z = 123; +>z : Symbol(z, Decl(deferredCallbacks.ts, 159, 7)) + + recreateDeferred1(doStuff)(() => { +>recreateDeferred1 : Symbol(recreateDeferred1, Decl(deferredCallbacks.ts, 136, 91)) +>doStuff : Symbol(doStuff, Decl(deferredCallbacks.ts, 130, 38)) + + z = "hi"; +>z : Symbol(z, Decl(deferredCallbacks.ts, 159, 7)) + + }); + z; // string | number +>z : Symbol(z, Decl(deferredCallbacks.ts, 159, 7)) +} + +function ff4() { +>ff4 : Symbol(ff4, Decl(deferredCallbacks.ts, 165, 1)) + + let z: string | number; +>z : Symbol(z, Decl(deferredCallbacks.ts, 168, 7)) + + z = 123; +>z : Symbol(z, Decl(deferredCallbacks.ts, 168, 7)) + + recreateDeferred2(doStuff)(() => { +>recreateDeferred2 : Symbol(recreateDeferred2, Decl(deferredCallbacks.ts, 137, 109)) +>doStuff : Symbol(doStuff, Decl(deferredCallbacks.ts, 130, 38)) + + z = "hi"; +>z : Symbol(z, Decl(deferredCallbacks.ts, 168, 7)) + + }); + z; // number +>z : Symbol(z, Decl(deferredCallbacks.ts, 168, 7)) +} + +// https://github.com/microsoft/TypeScript/issues/11498 + +declare function mystery(cb: () => void): void; +>mystery : Symbol(mystery, Decl(deferredCallbacks.ts, 174, 1)) +>cb : Symbol(cb, Decl(deferredCallbacks.ts, 178, 25)) + +function fx1() { +>fx1 : Symbol(fx1, Decl(deferredCallbacks.ts, 178, 47)) + + let x: string | number = "OK"; +>x : Symbol(x, Decl(deferredCallbacks.ts, 181, 7)) + + x; // string +>x : Symbol(x, Decl(deferredCallbacks.ts, 181, 7)) + + mystery(() => { +>mystery : Symbol(mystery, Decl(deferredCallbacks.ts, 174, 1)) + + x = 10; +>x : Symbol(x, Decl(deferredCallbacks.ts, 181, 7)) + + }); + x; // string | number +>x : Symbol(x, Decl(deferredCallbacks.ts, 181, 7)) + + if (x === 10) {} +>x : Symbol(x, Decl(deferredCallbacks.ts, 181, 7)) +} + +// https://github.com/microsoft/TypeScript/issues/15380 + +class Foo { +>Foo : Symbol(Foo, Decl(deferredCallbacks.ts, 188, 1)) + + public bar: string = ""; +>bar : Symbol(Foo.bar, Decl(deferredCallbacks.ts, 192, 11)) +} + +function fx2() { +>fx2 : Symbol(fx2, Decl(deferredCallbacks.ts, 194, 1)) + + let foo: Foo | null = null; +>foo : Symbol(foo, Decl(deferredCallbacks.ts, 197, 5)) +>Foo : Symbol(Foo, Decl(deferredCallbacks.ts, 188, 1)) + + [1].forEach((item) => { +>[1].forEach : Symbol(Array.forEach, Decl(lib.es5.d.ts, --, --)) +>forEach : Symbol(Array.forEach, Decl(lib.es5.d.ts, --, --)) +>item : Symbol(item, Decl(deferredCallbacks.ts, 198, 15)) + + foo = new Foo(); +>foo : Symbol(foo, Decl(deferredCallbacks.ts, 197, 5)) +>Foo : Symbol(Foo, Decl(deferredCallbacks.ts, 188, 1)) + + }); + if (foo) { +>foo : Symbol(foo, Decl(deferredCallbacks.ts, 197, 5)) + + foo.bar; +>foo.bar : Symbol(Foo.bar, Decl(deferredCallbacks.ts, 192, 11)) +>foo : Symbol(foo, Decl(deferredCallbacks.ts, 197, 5)) +>bar : Symbol(Foo.bar, Decl(deferredCallbacks.ts, 192, 11)) + } +} + +// https://github.com/microsoft/TypeScript/issues/57880 + +const call = (f: () => void) => f(); +>call : Symbol(call, Decl(deferredCallbacks.ts, 208, 5)) +>f : Symbol(f, Decl(deferredCallbacks.ts, 208, 14)) +>f : Symbol(f, Decl(deferredCallbacks.ts, 208, 14)) + +const fx3 = () => { +>fx3 : Symbol(fx3, Decl(deferredCallbacks.ts, 210, 5)) + + let a: undefined | number = undefined; +>a : Symbol(a, Decl(deferredCallbacks.ts, 211, 7)) +>undefined : Symbol(undefined) + + call(() => { a = 1; }); +>call : Symbol(call, Decl(deferredCallbacks.ts, 208, 5)) +>a : Symbol(a, Decl(deferredCallbacks.ts, 211, 7)) + + if (a !== undefined) { +>a : Symbol(a, Decl(deferredCallbacks.ts, 211, 7)) +>undefined : Symbol(undefined) + + a.toString(); +>a.toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --)) +>a : Symbol(a, Decl(deferredCallbacks.ts, 211, 7)) +>toString : Symbol(Number.toString, Decl(lib.es5.d.ts, --, --)) + } +}; + +// https://github.com/microsoft/TypeScript/issues/58291 + +async function execute(onError: (_err: Error | undefined) => void) { +>execute : Symbol(execute, Decl(deferredCallbacks.ts, 216, 2)) +>onError : Symbol(onError, Decl(deferredCallbacks.ts, 220, 23)) +>_err : Symbol(_err, Decl(deferredCallbacks.ts, 220, 33)) +>Error : Symbol(Error, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2022.error.d.ts, --, --)) + + onError(new Error("a")); +>onError : Symbol(onError, Decl(deferredCallbacks.ts, 220, 23)) +>Error : Symbol(Error, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2022.error.d.ts, --, --)) +} + +async function run() { +>run : Symbol(run, Decl(deferredCallbacks.ts, 222, 1)) + + let result: boolean = true; +>result : Symbol(result, Decl(deferredCallbacks.ts, 225, 7)) + + await execute(() => { +>execute : Symbol(execute, Decl(deferredCallbacks.ts, 216, 2)) + + result = false; +>result : Symbol(result, Decl(deferredCallbacks.ts, 225, 7)) + + }); + if (result === false) { +>result : Symbol(result, Decl(deferredCallbacks.ts, 225, 7)) + + console.log("error"); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) + } + return result; +>result : Symbol(result, Decl(deferredCallbacks.ts, 225, 7)) +} + diff --git a/tests/baselines/reference/deferredCallbacks.types b/tests/baselines/reference/deferredCallbacks.types new file mode 100644 index 00000000000..a0cd92c7b6c --- /dev/null +++ b/tests/baselines/reference/deferredCallbacks.types @@ -0,0 +1,1035 @@ +//// [tests/cases/compiler/deferredCallbacks.ts] //// + +=== deferredCallbacks.ts === +declare function immediate(cb: () => void): void; +>immediate : (cb: () => void) => void +> : ^ ^^ ^^^^^ +>cb : () => void +> : ^^^^^^ + +declare function deferred1(deferred cb: () => void): void; +>deferred1 : (cb: () => void) => void +> : ^ ^^ ^^^^^ +>cb : () => void +> : ^^^^^^ + +declare function deferred2(/** @deferred */ cb: () => void): void; +>deferred2 : (cb: () => void) => void +> : ^ ^^ ^^^^^ +>cb : () => void +> : ^^^^^^ + +declare function deferred3(/** @deferred */ deferred cb: () => void): void; +>deferred3 : (cb: () => void) => void +> : ^ ^^ ^^^^^ +>cb : () => void +> : ^^^^^^ + +function f01() { +>f01 : () => void +> : ^^^^^^^^^^ + + let x: string | number = "OK"; +>x : string | number +> : ^^^^^^^^^^^^^^^ +>"OK" : "OK" +> : ^^^^ + + immediate(() => { +>immediate(() => { x = 42; }) : void +> : ^^^^ +>immediate : (cb: () => void) => void +> : ^ ^^ ^^^^^ +>() => { x = 42; } : () => void +> : ^^^^^^^^^^ + + x = 42; +>x = 42 : 42 +> : ^^ +>x : string | number +> : ^^^^^^^^^^^^^^^ +>42 : 42 +> : ^^ + + }); + x; // string | number +>x : string | number +> : ^^^^^^^^^^^^^^^ +} + +function f02() { +>f02 : () => void +> : ^^^^^^^^^^ + + let x: string | number = "OK"; +>x : string | number +> : ^^^^^^^^^^^^^^^ +>"OK" : "OK" +> : ^^^^ + + deferred1(() => { +>deferred1(() => { x = 42; }) : void +> : ^^^^ +>deferred1 : (cb: () => void) => void +> : ^ ^^ ^^^^^ +>() => { x = 42; } : () => void +> : ^^^^^^^^^^ + + x = 42; +>x = 42 : 42 +> : ^^ +>x : string | number +> : ^^^^^^^^^^^^^^^ +>42 : 42 +> : ^^ + + }); + x; // string +>x : string +> : ^^^^^^ +} + +function f03() { +>f03 : () => void +> : ^^^^^^^^^^ + + let x: string | number = "OK"; +>x : string | number +> : ^^^^^^^^^^^^^^^ +>"OK" : "OK" +> : ^^^^ + + deferred2(() => { +>deferred2(() => { x = 42; }) : void +> : ^^^^ +>deferred2 : (cb: () => void) => void +> : ^ ^^ ^^^^^ +>() => { x = 42; } : () => void +> : ^^^^^^^^^^ + + x = 42; +>x = 42 : 42 +> : ^^ +>x : string | number +> : ^^^^^^^^^^^^^^^ +>42 : 42 +> : ^^ + + }); + x; // string +>x : string +> : ^^^^^^ +} + +function f04() { +>f04 : () => void +> : ^^^^^^^^^^ + + let x: string | number = "OK"; +>x : string | number +> : ^^^^^^^^^^^^^^^ +>"OK" : "OK" +> : ^^^^ + + deferred3(() => { +>deferred3(() => { x = 42; }) : void +> : ^^^^ +>deferred3 : (cb: () => void) => void +> : ^ ^^ ^^^^^ +>() => { x = 42; } : () => void +> : ^^^^^^^^^^ + + x = 42; +>x = 42 : 42 +> : ^^ +>x : string | number +> : ^^^^^^^^^^^^^^^ +>42 : 42 +> : ^^ + + }); + x; // string +>x : string +> : ^^^^^^ +} + +// Parameter is considered deferred if one or more overloads defer that parameter + +declare function overloaded(cb: (x: T) => T): void; +>overloaded : { (cb: (x: T) => T): void; (cb: (x: T_1, y: T_1) => T_1): void; (cb: (...args: any) => any): void; } +> : ^^^ ^^ ^^ ^^^ ^^^^^^^^ ^^ ^^^ ^^^ ^^ ^^^ ^^^ +>cb : (x: T) => T +> : ^ ^^ ^^^^^ +>x : T +> : ^ + +declare function overloaded(cb: (x: T, y: T) => T): void; +>overloaded : { (cb: (x: T_1) => T_1): void; (cb: (x: T, y: T) => T): void; (cb: (...args: any) => any): void; } +> : ^^^^^^^^ ^^ ^^^ ^^^ ^^ ^^ ^^^ ^^^ ^^ ^^^ ^^^ +>cb : (x: T, y: T) => T +> : ^ ^^ ^^ ^^ ^^^^^ +>x : T +> : ^ +>y : T +> : ^ + +declare function overloaded(deferred cb: (...args: any) => any): void; +>overloaded : { (cb: (x: T) => T): void; (cb: (x: T, y: T) => T): void; (cb: (...args: any) => any): void; } +> : ^^^ ^^ ^^ ^^^ ^^^ ^^ ^^ ^^^ ^^^ ^^ ^^^ ^^^ +>cb : (...args: any) => any +> : ^^^^ ^^ ^^^^^ +>args : any +> : ^^^ + +function f05() { +>f05 : () => void +> : ^^^^^^^^^^ + + let x: string | number = "OK"; +>x : string | number +> : ^^^^^^^^^^^^^^^ +>"OK" : "OK" +> : ^^^^ + + overloaded(() => { +>overloaded(() => { x = 42; }) : void +> : ^^^^ +>overloaded : { (cb: (x: T) => T): void; (cb: (x: T, y: T) => T): void; (cb: (...args: any) => any): void; } +> : ^^^ ^^ ^^ ^^^ ^^^ ^^ ^^ ^^^ ^^^ ^^ ^^^ ^^^ +>() => { x = 42; } : () => void +> : ^^^^^^^^^^ + + x = 42; +>x = 42 : 42 +> : ^^ +>x : string | number +> : ^^^^^^^^^^^^^^^ +>42 : 42 +> : ^^ + + }); + x.length; +>x.length : number +> : ^^^^^^ +>x : string +> : ^^^^^^ +>length : number +> : ^^^^^^ +} + +// deferred is permitted on a rest parameter + +declare function invokeImmediate(...args: ((...args: any) => any)[]): void; +>invokeImmediate : (...args: ((...args: any) => any)[]) => void +> : ^^^^ ^^ ^^^^^ +>args : ((...args: any) => any)[] +> : ^^^^^ ^^ ^^^^^ ^^^ +>args : any +> : ^^^ + +declare function invokeDeferred(deferred ...args: ((...args: any) => any)[]): void; +>invokeDeferred : (...args: ((...args: any) => any)[]) => void +> : ^^^^ ^^ ^^^^^ +>args : ((...args: any) => any)[] +> : ^^^^^ ^^ ^^^^^ ^^^ +>args : any +> : ^^^ + +function f06() { +>f06 : () => void +> : ^^^^^^^^^^ + + let a = []; +>a : any[] +> : ^^^^^ +>[] : never[] +> : ^^^^^^^ + + a.push("abc"); +>a.push("abc") : number +> : ^^^^^^ +>a.push : (...items: any[]) => number +> : ^^^^ ^^^^^^^^^^^^ +>a : any[] +> : ^^^^^ +>push : (...items: any[]) => number +> : ^^^^ ^^^^^^^^^^^^ +>"abc" : "abc" +> : ^^^^^ + + a; // string[] +>a : string[] +> : ^^^^^^^^ + + invokeImmediate( +>invokeImmediate( () => { a; // string[] a.push(42); a; // (string | number)[] }, () => { a; // string[] a.push(true); a; // (string | boolean)[] } ) : void +> : ^^^^ +>invokeImmediate : (...args: ((...args: any) => any)[]) => void +> : ^^^^ ^^ ^^^^^ + + () => { +>() => { a; // string[] a.push(42); a; // (string | number)[] } : () => void +> : ^^^^^^^^^^ + + a; // string[] +>a : string[] +> : ^^^^^^^^ + + a.push(42); +>a.push(42) : number +> : ^^^^^^ +>a.push : (...items: any[]) => number +> : ^^^^ ^^^^^^^^^^^^ +>a : any[] +> : ^^^^^ +>push : (...items: any[]) => number +> : ^^^^ ^^^^^^^^^^^^ +>42 : 42 +> : ^^ + + a; // (string | number)[] +>a : (string | number)[] +> : ^^^^^^^^^^^^^^^^^^^ + + }, + () => { +>() => { a; // string[] a.push(true); a; // (string | boolean)[] } : () => void +> : ^^^^^^^^^^ + + a; // string[] +>a : string[] +> : ^^^^^^^^ + + a.push(true); +>a.push(true) : number +> : ^^^^^^ +>a.push : (...items: any[]) => number +> : ^^^^ ^^^^^^^^^^^^ +>a : any[] +> : ^^^^^ +>push : (...items: any[]) => number +> : ^^^^ ^^^^^^^^^^^^ +>true : true +> : ^^^^ + + a; // (string | boolean)[] +>a : (string | boolean)[] +> : ^^^^^^^^^^^^^^^^^^^^ + } + ); + a; // (string | number | boolean)[] +>a : (string | number | boolean)[] +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +} + +function f07() { +>f07 : () => void +> : ^^^^^^^^^^ + + let a = []; +>a : any[] +> : ^^^^^ +>[] : never[] +> : ^^^^^^^ + + a.push("abc"); +>a.push("abc") : number +> : ^^^^^^ +>a.push : (...items: any[]) => number +> : ^^^^ ^^^^^^^^^^^^ +>a : any[] +> : ^^^^^ +>push : (...items: any[]) => number +> : ^^^^ ^^^^^^^^^^^^ +>"abc" : "abc" +> : ^^^^^ + + a; // string[] +>a : string[] +> : ^^^^^^^^ + + invokeDeferred( +>invokeDeferred( () => { a; // string[] a.push(42); a; // (string | number)[] }, () => { a; // string[] a.push(true); a; // (string | boolean)[] } ) : void +> : ^^^^ +>invokeDeferred : (...args: ((...args: any) => any)[]) => void +> : ^^^^ ^^ ^^^^^ + + () => { +>() => { a; // string[] a.push(42); a; // (string | number)[] } : () => void +> : ^^^^^^^^^^ + + a; // string[] +>a : string[] +> : ^^^^^^^^ + + a.push(42); +>a.push(42) : number +> : ^^^^^^ +>a.push : (...items: any[]) => number +> : ^^^^ ^^^^^^^^^^^^ +>a : any[] +> : ^^^^^ +>push : (...items: any[]) => number +> : ^^^^ ^^^^^^^^^^^^ +>42 : 42 +> : ^^ + + a; // (string | number)[] +>a : (string | number)[] +> : ^^^^^^^^^^^^^^^^^^^ + + }, + () => { +>() => { a; // string[] a.push(true); a; // (string | boolean)[] } : () => void +> : ^^^^^^^^^^ + + a; // string[] +>a : string[] +> : ^^^^^^^^ + + a.push(true); +>a.push(true) : number +> : ^^^^^^ +>a.push : (...items: any[]) => number +> : ^^^^ ^^^^^^^^^^^^ +>a : any[] +> : ^^^^^ +>push : (...items: any[]) => number +> : ^^^^ ^^^^^^^^^^^^ +>true : true +> : ^^^^ + + a; // (string | boolean)[] +>a : (string | boolean)[] +> : ^^^^^^^^^^^^^^^^^^^^ + } + ); + a; // string[] +>a : string[] +> : ^^^^^^^^ +} + +// deferred modifier must precede public/private/protected/readonly + +class CC { +>CC : CC +> : ^^ + + constructor(deferred public readonly x: () => void) {} +>x : () => void +> : ^^^^^^ +} + +// deferred requires parameter to have type that permits functions + +declare function f10(deferred f: () => void): void; +>f10 : (f: () => void) => void +> : ^ ^^ ^^^^^ +>f : () => void +> : ^^^^^^ + +declare function f11(deferred f: Function): void; +>f11 : (f: Function) => void +> : ^ ^^ ^^^^^ +>f : Function +> : ^^^^^^^^ + +declare function f12(deferred f: any): void; +>f12 : (f: any) => void +> : ^ ^^ ^^^^^ +>f : any +> : ^^^ + +declare function f13(deferred f: object): void; +>f13 : (f: object) => void +> : ^ ^^ ^^^^^ +>f : object +> : ^^^^^^ + +declare function f14(deferred f: {}): void; +>f14 : (f: {}) => void +> : ^ ^^ ^^^^^ +>f : {} +> : ^^ + +declare function f15(deferred f: unknown): void; +>f15 : (f: unknown) => void +> : ^ ^^ ^^^^^ +>f : unknown +> : ^^^^^^^ + +declare function f16(deferred f: T): void; +>f16 : (f: T) => void +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>f : T +> : ^ + +declare function f17 any>(deferred f: T): void; +>f17 : any>(f: T) => void +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>args : any +> : ^^^ +>f : T +> : ^ + +declare function f18 void)>(deferred f: T): void; +>f18 : void)>(f: T) => void +> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^ +>f : T +> : ^ + +declare function f20(deferred ...funcs: Function[]): void; +>f20 : (...funcs: Function[]) => void +> : ^^^^ ^^ ^^^^^ +>funcs : Function[] +> : ^^^^^^^^^^ + +declare function f21 any)[]>(deferred ...funcs: T): void; +>f21 : any)[]>(...funcs: T) => void +> : ^ ^^^^^^^^^ ^^^^^ ^^ ^^^^^ +>args : any +> : ^^^ +>funcs : T +> : ^ + +declare function f22 void))[]>(deferred ...funcs: T): void; +>f22 : void))[]>(...funcs: T) => void +> : ^ ^^^^^^^^^ ^^^^^ ^^ ^^^^^ +>funcs : T +> : ^ + +declare function f23 void)[]>(deferred ...funcs: T): void; +>f23 : void)[]>(...funcs: T) => void +> : ^ ^^^^^^^^^ ^^^^^ ^^ ^^^^^ +>funcs : T +> : ^ + +declare function f24 void)[]>(deferred ...funcs: T | string[]): void; +>f24 : void)[]>(...funcs: T | string[]) => void +> : ^ ^^^^^^^^^ ^^^^^ ^^ ^^^^^ +>funcs : string[] | T +> : ^^^^^^^^^^^^ + +declare function f30(deferred f: { foo(): void }): void; +>f30 : (f: { foo(): void; }) => void +> : ^ ^^ ^^^^^ +>f : { foo(): void; } +> : ^^^^^^^^^ ^^^ +>foo : () => void +> : ^^^^^^ + +declare function f31(deferred f: number): void; +>f31 : (f: number) => void +> : ^ ^^ ^^^^^ +>f : number +> : ^^^^^^ + +declare function f32(deferred ...funcs: number[]): void; +>f32 : (...funcs: number[]) => void +> : ^^^^ ^^ ^^^^^ +>funcs : number[] +> : ^^^^^^^^ + +type T10 = (deferred f: () => void) => void; +>T10 : T10 +> : ^^^ +>f : () => void +> : ^^^^^^ + +type T11 = (deferred f: { (): void }) => void; +>T11 : T11 +> : ^^^ +>f : () => void +> : ^^^^^^ + +type T12 = (deferred f: Function) => void; +>T12 : T12 +> : ^^^ +>f : Function +> : ^^^^^^^^ + +type T13 = (deferred f: any) => void; +>T13 : T13 +> : ^^^ +>f : any +> : ^^^ + +type T20 = (deferred f: { foo(): void }) => void; +>T20 : T20 +> : ^^^ +>f : { foo(): void; } +> : ^^^^^^^^^ ^^^ +>foo : () => void +> : ^^^^^^ + +type T21 = (deferred f: number) => void; +>T21 : T21 +> : ^^^ +>f : number +> : ^^^^^^ + +type T22 = (deferred ...funcs: number[]) => void; +>T22 : T22 +> : ^^^ +>funcs : number[] +> : ^^^^^^^^ + +type T23 = { deferred x: () => void }; +>T23 : T23 +> : ^^^ +>x : () => void +> : ^^^^^^ + +// deferred modifier is not captured in argument list tuples + +declare function doStuff(deferred f: () => void): void; +>doStuff : (f: () => void) => void +> : ^ ^^ ^^^^^ +>f : () => void +> : ^^^^^^ + +declare function recreate(f: (...args: A) => R): (...args: A) => R; +>recreate : (f: (...args: A) => R) => (...args: A) => R +> : ^ ^^^^^^^^^ ^^ ^^ ^^ ^^^^^ +>f : (...args: A) => R +> : ^^^^ ^^ ^^^^^ +>args : A +> : ^ +>args : A +> : ^ + +declare function recreateDeferred1(f: (deferred ...args: A) => R): (...args: A) => R; +>recreateDeferred1 : (f: (deferred ...args: A) => R) => (...args: A) => R +> : ^ ^^^^^^^^^ ^^ ^^ ^^ ^^^^^ +>f : (...args: A) => R +> : ^^^^ ^^ ^^^^^ +>args : A +> : ^ +>args : A +> : ^ + +declare function recreateDeferred2(f: (...args: A) => R): (deferred ...args: A) => R; +>recreateDeferred2 : (f: (...args: A) => R) => (deferred ...args: A) => R +> : ^ ^^^^^^^^^ ^^ ^^ ^^ ^^^^^ +>f : (...args: A) => R +> : ^^^^ ^^ ^^^^^ +>args : A +> : ^ +>args : A +> : ^ + +function ff1() { +>ff1 : () => void +> : ^^^^^^^^^^ + + let x: string | number; +>x : string | number +> : ^^^^^^^^^^^^^^^ + + x = 123; +>x = 123 : 123 +> : ^^^ +>x : string | number +> : ^^^^^^^^^^^^^^^ +>123 : 123 +> : ^^^ + + doStuff(() => { +>doStuff(() => { x = "hi"; }) : void +> : ^^^^ +>doStuff : (f: () => void) => void +> : ^ ^^ ^^^^^ +>() => { x = "hi"; } : () => void +> : ^^^^^^^^^^ + + x = "hi"; +>x = "hi" : "hi" +> : ^^^^ +>x : string | number +> : ^^^^^^^^^^^^^^^ +>"hi" : "hi" +> : ^^^^ + + }); + x; // number +>x : number +> : ^^^^^^ +} + +function ff2() { +>ff2 : () => void +> : ^^^^^^^^^^ + + let y: string | number; +>y : string | number +> : ^^^^^^^^^^^^^^^ + + y = 123; +>y = 123 : 123 +> : ^^^ +>y : string | number +> : ^^^^^^^^^^^^^^^ +>123 : 123 +> : ^^^ + + recreate(doStuff)(() => { +>recreate(doStuff)(() => { y = "hi"; }) : void +> : ^^^^ +>recreate(doStuff) : (f: () => void) => void +> : ^^^^^^^^^^ ^^^^^^^^^ +>recreate : (f: (...args: A) => R) => (...args: A) => R +> : ^ ^^^^^^^^^ ^^ ^^ ^^ ^^^^^ +>doStuff : (f: () => void) => void +> : ^ ^^ ^^^^^ +>() => { y = "hi"; } : () => void +> : ^^^^^^^^^^ + + y = "hi"; +>y = "hi" : "hi" +> : ^^^^ +>y : string | number +> : ^^^^^^^^^^^^^^^ +>"hi" : "hi" +> : ^^^^ + + }); + y; // string | number +>y : string | number +> : ^^^^^^^^^^^^^^^ +} + +function ff3() { +>ff3 : () => void +> : ^^^^^^^^^^ + + let z: string | number; +>z : string | number +> : ^^^^^^^^^^^^^^^ + + z = 123; +>z = 123 : 123 +> : ^^^ +>z : string | number +> : ^^^^^^^^^^^^^^^ +>123 : 123 +> : ^^^ + + recreateDeferred1(doStuff)(() => { +>recreateDeferred1(doStuff)(() => { z = "hi"; }) : void +> : ^^^^ +>recreateDeferred1(doStuff) : (f: () => void) => void +> : ^^^^^^^^^^ ^^^^^^^^^ +>recreateDeferred1 : (f: (deferred ...args: A) => R) => (...args: A) => R +> : ^ ^^^^^^^^^ ^^ ^^ ^^ ^^^^^ +>doStuff : (f: () => void) => void +> : ^ ^^ ^^^^^ +>() => { z = "hi"; } : () => void +> : ^^^^^^^^^^ + + z = "hi"; +>z = "hi" : "hi" +> : ^^^^ +>z : string | number +> : ^^^^^^^^^^^^^^^ +>"hi" : "hi" +> : ^^^^ + + }); + z; // string | number +>z : string | number +> : ^^^^^^^^^^^^^^^ +} + +function ff4() { +>ff4 : () => void +> : ^^^^^^^^^^ + + let z: string | number; +>z : string | number +> : ^^^^^^^^^^^^^^^ + + z = 123; +>z = 123 : 123 +> : ^^^ +>z : string | number +> : ^^^^^^^^^^^^^^^ +>123 : 123 +> : ^^^ + + recreateDeferred2(doStuff)(() => { +>recreateDeferred2(doStuff)(() => { z = "hi"; }) : void +> : ^^^^ +>recreateDeferred2(doStuff) : (f: () => void) => void +> : ^^^^^^^^^^ ^^^^^^^^^ +>recreateDeferred2 : (f: (...args: A) => R) => (deferred ...args: A) => R +> : ^ ^^^^^^^^^ ^^ ^^ ^^ ^^^^^ +>doStuff : (f: () => void) => void +> : ^ ^^ ^^^^^ +>() => { z = "hi"; } : () => void +> : ^^^^^^^^^^ + + z = "hi"; +>z = "hi" : "hi" +> : ^^^^ +>z : string | number +> : ^^^^^^^^^^^^^^^ +>"hi" : "hi" +> : ^^^^ + + }); + z; // number +>z : number +> : ^^^^^^ +} + +// https://github.com/microsoft/TypeScript/issues/11498 + +declare function mystery(cb: () => void): void; +>mystery : (cb: () => void) => void +> : ^ ^^ ^^^^^ +>cb : () => void +> : ^^^^^^ + +function fx1() { +>fx1 : () => void +> : ^^^^^^^^^^ + + let x: string | number = "OK"; +>x : string | number +> : ^^^^^^^^^^^^^^^ +>"OK" : "OK" +> : ^^^^ + + x; // string +>x : string +> : ^^^^^^ + + mystery(() => { +>mystery(() => { x = 10; }) : void +> : ^^^^ +>mystery : (cb: () => void) => void +> : ^ ^^ ^^^^^ +>() => { x = 10; } : () => void +> : ^^^^^^^^^^ + + x = 10; +>x = 10 : 10 +> : ^^ +>x : string | number +> : ^^^^^^^^^^^^^^^ +>10 : 10 +> : ^^ + + }); + x; // string | number +>x : string | number +> : ^^^^^^^^^^^^^^^ + + if (x === 10) {} +>x === 10 : boolean +> : ^^^^^^^ +>x : string | number +> : ^^^^^^^^^^^^^^^ +>10 : 10 +> : ^^ +} + +// https://github.com/microsoft/TypeScript/issues/15380 + +class Foo { +>Foo : Foo +> : ^^^ + + public bar: string = ""; +>bar : string +> : ^^^^^^ +>"" : "" +> : ^^ +} + +function fx2() { +>fx2 : () => void +> : ^^^^^^^^^^ + + let foo: Foo | null = null; +>foo : Foo | null +> : ^^^^^^^^^^ + + [1].forEach((item) => { +>[1].forEach((item) => { foo = new Foo(); }) : void +> : ^^^^ +>[1].forEach : (callbackfn: (value: number, index: number, array: number[]) => void, thisArg?: any) => void +> : ^ ^^^ ^^^^^^^^^^ ^^ ^^ ^^^^^^^^^^^^^^^ ^^ ^^^ ^^^^^ +>[1] : number[] +> : ^^^^^^^^ +>1 : 1 +> : ^ +>forEach : (callbackfn: (value: number, index: number, array: number[]) => void, thisArg?: any) => void +> : ^ ^^^ ^^^^^^^^^^ ^^ ^^ ^^^^^^^^^^^^^^^ ^^ ^^^ ^^^^^ +>(item) => { foo = new Foo(); } : (item: number) => void +> : ^ ^^^^^^^^^^^^^^^^^ +>item : number +> : ^^^^^^ + + foo = new Foo(); +>foo = new Foo() : Foo +> : ^^^ +>foo : Foo | null +> : ^^^^^^^^^^ +>new Foo() : Foo +> : ^^^ +>Foo : typeof Foo +> : ^^^^^^^^^^ + + }); + if (foo) { +>foo : Foo | null +> : ^^^^^^^^^^ + + foo.bar; +>foo.bar : string +> : ^^^^^^ +>foo : Foo +> : ^^^ +>bar : string +> : ^^^^^^ + } +} + +// https://github.com/microsoft/TypeScript/issues/57880 + +const call = (f: () => void) => f(); +>call : (f: () => void) => void +> : ^ ^^ ^^^^^^^^^ +>(f: () => void) => f() : (f: () => void) => void +> : ^ ^^ ^^^^^^^^^ +>f : () => void +> : ^^^^^^ +>f() : void +> : ^^^^ +>f : () => void +> : ^^^^^^ + +const fx3 = () => { +>fx3 : () => void +> : ^^^^^^^^^^ +>() => { let a: undefined | number = undefined; call(() => { a = 1; }); if (a !== undefined) { a.toString(); }} : () => void +> : ^^^^^^^^^^ + + let a: undefined | number = undefined; +>a : number | undefined +> : ^^^^^^^^^^^^^^^^^^ +>undefined : undefined +> : ^^^^^^^^^ + + call(() => { a = 1; }); +>call(() => { a = 1; }) : void +> : ^^^^ +>call : (f: () => void) => void +> : ^ ^^ ^^^^^^^^^ +>() => { a = 1; } : () => void +> : ^^^^^^^^^^ +>a = 1 : 1 +> : ^ +>a : number | undefined +> : ^^^^^^^^^^^^^^^^^^ +>1 : 1 +> : ^ + + if (a !== undefined) { +>a !== undefined : boolean +> : ^^^^^^^ +>a : number | undefined +> : ^^^^^^^^^^^^^^^^^^ +>undefined : undefined +> : ^^^^^^^^^ + + a.toString(); +>a.toString() : string +> : ^^^^^^ +>a.toString : (radix?: number) => string +> : ^ ^^^ ^^^^^ +>a : number +> : ^^^^^^ +>toString : (radix?: number) => string +> : ^ ^^^ ^^^^^ + } +}; + +// https://github.com/microsoft/TypeScript/issues/58291 + +async function execute(onError: (_err: Error | undefined) => void) { +>execute : (onError: (_err: Error | undefined) => void) => Promise +> : ^ ^^ ^^^^^^^^^^^^^^^^^^ +>onError : (_err: Error | undefined) => void +> : ^ ^^ ^^^^^ +>_err : Error | undefined +> : ^^^^^^^^^^^^^^^^^ + + onError(new Error("a")); +>onError(new Error("a")) : void +> : ^^^^ +>onError : (_err: Error | undefined) => void +> : ^ ^^ ^^^^^ +>new Error("a") : Error +> : ^^^^^ +>Error : ErrorConstructor +> : ^^^^^^^^^^^^^^^^ +>"a" : "a" +> : ^^^ +} + +async function run() { +>run : () => Promise +> : ^^^^^^^^^^^^^^^^^^^^^^ + + let result: boolean = true; +>result : boolean +> : ^^^^^^^ +>true : true +> : ^^^^ + + await execute(() => { +>await execute(() => { result = false; }) : void +> : ^^^^ +>execute(() => { result = false; }) : Promise +> : ^^^^^^^^^^^^^ +>execute : (onError: (_err: Error | undefined) => void) => Promise +> : ^ ^^ ^^^^^^^^^^^^^^^^^^ +>() => { result = false; } : () => void +> : ^^^^^^^^^^ + + result = false; +>result = false : false +> : ^^^^^ +>result : boolean +> : ^^^^^^^ +>false : false +> : ^^^^^ + + }); + if (result === false) { +>result === false : boolean +> : ^^^^^^^ +>result : boolean +> : ^^^^^^^ +>false : false +> : ^^^^^ + + console.log("error"); +>console.log("error") : void +> : ^^^^ +>console.log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>console : Console +> : ^^^^^^^ +>log : (...data: any[]) => void +> : ^^^^ ^^ ^^^^^ +>"error" : "error" +> : ^^^^^^^ + } + return result; +>result : boolean +> : ^^^^^^^ +} + diff --git a/tests/cases/compiler/deferredCallbacks.ts b/tests/cases/compiler/deferredCallbacks.ts new file mode 100644 index 00000000000..33f324704c2 --- /dev/null +++ b/tests/cases/compiler/deferredCallbacks.ts @@ -0,0 +1,238 @@ +// @strict: true +// @declaration: true +// @target: esnext + +declare function immediate(cb: () => void): void; +declare function deferred1(deferred cb: () => void): void; +declare function deferred2(/** @deferred */ cb: () => void): void; +declare function deferred3(/** @deferred */ deferred cb: () => void): void; + +function f01() { + let x: string | number = "OK"; + immediate(() => { + x = 42; + }); + x; // string | number +} + +function f02() { + let x: string | number = "OK"; + deferred1(() => { + x = 42; + }); + x; // string +} + +function f03() { + let x: string | number = "OK"; + deferred2(() => { + x = 42; + }); + x; // string +} + +function f04() { + let x: string | number = "OK"; + deferred3(() => { + x = 42; + }); + x; // string +} + +// Parameter is considered deferred if one or more overloads defer that parameter + +declare function overloaded(cb: (x: T) => T): void; +declare function overloaded(cb: (x: T, y: T) => T): void; +declare function overloaded(deferred cb: (...args: any) => any): void; + +function f05() { + let x: string | number = "OK"; + overloaded(() => { + x = 42; + }); + x.length; +} + +// deferred is permitted on a rest parameter + +declare function invokeImmediate(...args: ((...args: any) => any)[]): void; +declare function invokeDeferred(deferred ...args: ((...args: any) => any)[]): void; + +function f06() { + let a = []; + a.push("abc"); + a; // string[] + invokeImmediate( + () => { + a; // string[] + a.push(42); + a; // (string | number)[] + }, + () => { + a; // string[] + a.push(true); + a; // (string | boolean)[] + } + ); + a; // (string | number | boolean)[] +} + +function f07() { + let a = []; + a.push("abc"); + a; // string[] + invokeDeferred( + () => { + a; // string[] + a.push(42); + a; // (string | number)[] + }, + () => { + a; // string[] + a.push(true); + a; // (string | boolean)[] + } + ); + a; // string[] +} + +// deferred modifier must precede public/private/protected/readonly + +class CC { + constructor(deferred public readonly x: () => void) {} +} + +// deferred requires parameter to have type that permits functions + +declare function f10(deferred f: () => void): void; +declare function f11(deferred f: Function): void; +declare function f12(deferred f: any): void; +declare function f13(deferred f: object): void; +declare function f14(deferred f: {}): void; +declare function f15(deferred f: unknown): void; +declare function f16(deferred f: T): void; +declare function f17 any>(deferred f: T): void; +declare function f18 void)>(deferred f: T): void; + +declare function f20(deferred ...funcs: Function[]): void; +declare function f21 any)[]>(deferred ...funcs: T): void; +declare function f22 void))[]>(deferred ...funcs: T): void; +declare function f23 void)[]>(deferred ...funcs: T): void; +declare function f24 void)[]>(deferred ...funcs: T | string[]): void; + +declare function f30(deferred f: { foo(): void }): void; +declare function f31(deferred f: number): void; +declare function f32(deferred ...funcs: number[]): void; + +type T10 = (deferred f: () => void) => void; +type T11 = (deferred f: { (): void }) => void; +type T12 = (deferred f: Function) => void; +type T13 = (deferred f: any) => void; + +type T20 = (deferred f: { foo(): void }) => void; +type T21 = (deferred f: number) => void; +type T22 = (deferred ...funcs: number[]) => void; +type T23 = { deferred x: () => void }; + +// deferred modifier is not captured in argument list tuples + +declare function doStuff(deferred f: () => void): void; + +declare function recreate(f: (...args: A) => R): (...args: A) => R; +declare function recreateDeferred1(f: (deferred ...args: A) => R): (...args: A) => R; +declare function recreateDeferred2(f: (...args: A) => R): (deferred ...args: A) => R; + +function ff1() { + let x: string | number; + x = 123; + doStuff(() => { + x = "hi"; + }); + x; // number +} + +function ff2() { + let y: string | number; + y = 123; + recreate(doStuff)(() => { + y = "hi"; + }); + y; // string | number +} + +function ff3() { + let z: string | number; + z = 123; + recreateDeferred1(doStuff)(() => { + z = "hi"; + }); + z; // string | number +} + +function ff4() { + let z: string | number; + z = 123; + recreateDeferred2(doStuff)(() => { + z = "hi"; + }); + z; // number +} + +// https://github.com/microsoft/TypeScript/issues/11498 + +declare function mystery(cb: () => void): void; + +function fx1() { + let x: string | number = "OK"; + x; // string + mystery(() => { + x = 10; + }); + x; // string | number + if (x === 10) {} +} + +// https://github.com/microsoft/TypeScript/issues/15380 + +class Foo { + public bar: string = ""; +} + +function fx2() { + let foo: Foo | null = null; + [1].forEach((item) => { + foo = new Foo(); + }); + if (foo) { + foo.bar; + } +} + +// https://github.com/microsoft/TypeScript/issues/57880 + +const call = (f: () => void) => f(); + +const fx3 = () => { + let a: undefined | number = undefined; + call(() => { a = 1; }); + if (a !== undefined) { + a.toString(); + } +}; + +// https://github.com/microsoft/TypeScript/issues/58291 + +async function execute(onError: (_err: Error | undefined) => void) { + onError(new Error("a")); +} + +async function run() { + let result: boolean = true; + await execute(() => { + result = false; + }); + if (result === false) { + console.log("error"); + } + return result; +}