From df3b5bbdab908e75cd7ed77317edc18d68f1a282 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 6 Jan 2020 08:55:34 -1000 Subject: [PATCH] Fix ThisParameterType type (#36013) * Simplify ThisParameterType type * Add tests --- src/lib/es5.d.ts | 2 +- .../reference/strictBindCallApply2.js | 16 +++++++++++++ .../reference/strictBindCallApply2.symbols | 24 +++++++++++++++++++ .../reference/strictBindCallApply2.types | 24 +++++++++++++++++++ .../functions/strictBindCallApply2.ts | 11 +++++++++ 5 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/strictBindCallApply2.js create mode 100644 tests/baselines/reference/strictBindCallApply2.symbols create mode 100644 tests/baselines/reference/strictBindCallApply2.types create mode 100644 tests/cases/conformance/functions/strictBindCallApply2.ts diff --git a/src/lib/es5.d.ts b/src/lib/es5.d.ts index 8c11be587a1..8893a7b0bb6 100644 --- a/src/lib/es5.d.ts +++ b/src/lib/es5.d.ts @@ -298,7 +298,7 @@ declare var Function: FunctionConstructor; /** * Extracts the type of the 'this' parameter of a function type, or 'unknown' if the function type has no 'this' parameter. */ -type ThisParameterType = T extends (this: unknown, ...args: any[]) => any ? unknown : T extends (this: infer U, ...args: any[]) => any ? U : unknown; +type ThisParameterType = T extends (this: infer U, ...args: any[]) => any ? U : unknown; /** * Removes the 'this' parameter from a function type. diff --git a/tests/baselines/reference/strictBindCallApply2.js b/tests/baselines/reference/strictBindCallApply2.js new file mode 100644 index 00000000000..d15b4114cbf --- /dev/null +++ b/tests/baselines/reference/strictBindCallApply2.js @@ -0,0 +1,16 @@ +//// [strictBindCallApply2.ts] +// Repro from #32964 + +interface Foo { blub: string }; +function fn(this: Foo) {} + +type Test = ThisParameterType; + +const fb = fn.bind({ blub: "blub" }); + + +//// [strictBindCallApply2.js] +// Repro from #32964 +; +function fn() { } +var fb = fn.bind({ blub: "blub" }); diff --git a/tests/baselines/reference/strictBindCallApply2.symbols b/tests/baselines/reference/strictBindCallApply2.symbols new file mode 100644 index 00000000000..015a796fb51 --- /dev/null +++ b/tests/baselines/reference/strictBindCallApply2.symbols @@ -0,0 +1,24 @@ +=== tests/cases/conformance/functions/strictBindCallApply2.ts === +// Repro from #32964 + +interface Foo { blub: string }; +>Foo : Symbol(Foo, Decl(strictBindCallApply2.ts, 0, 0)) +>blub : Symbol(Foo.blub, Decl(strictBindCallApply2.ts, 2, 15)) + +function fn(this: Foo) {} +>fn : Symbol(fn, Decl(strictBindCallApply2.ts, 2, 31)) +>this : Symbol(this, Decl(strictBindCallApply2.ts, 3, 12)) +>Foo : Symbol(Foo, Decl(strictBindCallApply2.ts, 0, 0)) + +type Test = ThisParameterType; +>Test : Symbol(Test, Decl(strictBindCallApply2.ts, 3, 25)) +>ThisParameterType : Symbol(ThisParameterType, Decl(lib.es5.d.ts, --, --)) +>fn : Symbol(fn, Decl(strictBindCallApply2.ts, 2, 31)) + +const fb = fn.bind({ blub: "blub" }); +>fb : Symbol(fb, Decl(strictBindCallApply2.ts, 7, 5)) +>fn.bind : Symbol(CallableFunction.bind, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --) ... and 1 more) +>fn : Symbol(fn, Decl(strictBindCallApply2.ts, 2, 31)) +>bind : Symbol(CallableFunction.bind, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --) ... and 1 more) +>blub : Symbol(blub, Decl(strictBindCallApply2.ts, 7, 20)) + diff --git a/tests/baselines/reference/strictBindCallApply2.types b/tests/baselines/reference/strictBindCallApply2.types new file mode 100644 index 00000000000..6abb106e66b --- /dev/null +++ b/tests/baselines/reference/strictBindCallApply2.types @@ -0,0 +1,24 @@ +=== tests/cases/conformance/functions/strictBindCallApply2.ts === +// Repro from #32964 + +interface Foo { blub: string }; +>blub : string + +function fn(this: Foo) {} +>fn : (this: Foo) => void +>this : Foo + +type Test = ThisParameterType; +>Test : Foo +>fn : (this: Foo) => void + +const fb = fn.bind({ blub: "blub" }); +>fb : () => void +>fn.bind({ blub: "blub" }) : () => void +>fn.bind : { (this: T, thisArg: ThisParameterType): OmitThisParameter; (this: (this: T, arg0: A0, ...args: A) => R, thisArg: T, arg0: A0): (...args: A) => R; (this: (this: T, arg0: A0, arg1: A1, ...args: A) => R, thisArg: T, arg0: A0, arg1: A1): (...args: A) => R; (this: (this: T, arg0: A0, arg1: A1, arg2: A2, ...args: A) => R, thisArg: T, arg0: A0, arg1: A1, arg2: A2): (...args: A) => R; (this: (this: T, arg0: A0, arg1: A1, arg2: A2, arg3: A3, ...args: A) => R, thisArg: T, arg0: A0, arg1: A1, arg2: A2, arg3: A3): (...args: A) => R; (this: (this: T, ...args: AX[]) => R, thisArg: T, ...args: AX[]): (...args: AX[]) => R; } +>fn : (this: Foo) => void +>bind : { (this: T, thisArg: ThisParameterType): OmitThisParameter; (this: (this: T, arg0: A0, ...args: A) => R, thisArg: T, arg0: A0): (...args: A) => R; (this: (this: T, arg0: A0, arg1: A1, ...args: A) => R, thisArg: T, arg0: A0, arg1: A1): (...args: A) => R; (this: (this: T, arg0: A0, arg1: A1, arg2: A2, ...args: A) => R, thisArg: T, arg0: A0, arg1: A1, arg2: A2): (...args: A) => R; (this: (this: T, arg0: A0, arg1: A1, arg2: A2, arg3: A3, ...args: A) => R, thisArg: T, arg0: A0, arg1: A1, arg2: A2, arg3: A3): (...args: A) => R; (this: (this: T, ...args: AX[]) => R, thisArg: T, ...args: AX[]): (...args: AX[]) => R; } +>{ blub: "blub" } : { blub: string; } +>blub : string +>"blub" : "blub" + diff --git a/tests/cases/conformance/functions/strictBindCallApply2.ts b/tests/cases/conformance/functions/strictBindCallApply2.ts new file mode 100644 index 00000000000..e32da1d59ec --- /dev/null +++ b/tests/cases/conformance/functions/strictBindCallApply2.ts @@ -0,0 +1,11 @@ +// @strictFunctionTypes: false +// @strictBindCallApply: true + +// Repro from #32964 + +interface Foo { blub: string }; +function fn(this: Foo) {} + +type Test = ThisParameterType; + +const fb = fn.bind({ blub: "blub" });