Repository: TypeScript
Issue: bind, call and apply do not work on unions of function types with different return types.
Labels: Suggestion,Awaiting More Feedback

<!-- Please try to reproduce the issue with `typescript@next`. It may have already been fixed. -->
**TypeScript Version:**  3.6.3

<!-- Search terms you tried before logging this (so others can find this issue more easily) -->
**Search Terms:**
call, bind, apply, function, functions, Function.prototype.call, Function.prototype.apply, Function.prototype.bind, union, return, this, strictBindCallApply
**Code**

```ts
type aFn = (this: string, value: string) => string;
type bFn = (this: string, value: string) => Promise<string>;

function callFn(callback: aFn | bFn): Promise<string> | string {
    return callback.call("hello", "world");
}

function applyFn(callback: aFn | bFn): Promise<string> | string {
    return callback.apply("hello", ["world"]);
}

function bindFn(callback: aFn | bFn): () => Promise<string> | string {
    return callback.bind("hello", "world");
}
```

**Expected behavior:**
Code compiles. The types in this code are equivalent to the types in the following example, which does compile:

```ts
type cFn = (this: string, value: string) => string | Promise<string>;

function callFn1(callback: cFn): Promise<string> | string {
    return callback.call("hello", "world");
}

function applyFn1(callback: cFn): Promise<string> | string {
    return callback.apply("hello", ["world"]);
}

function bindFn1(callback: cFn): () => Promise<string> | string {
    return callback.bind("hello", "world");
}
```

The only difference between the two examples is that the first uses a type union of function types `aFn` and `bFn`, which only differ in terms of return value, whereas the second uses a type union in the return value of `cFn`. In other words I think the union of type `aFn` and `bFn` should behave the same as type `cFn`.
```ts
type aFn = (this: string, value: string) => string;
type bFn = (this: string, value: string) => Promise<string>;
type cFn = (this: string, value: string) => string | Promise<string>;
```


**Actual behavior:**
```
example.ts(5,12): error TS2684: The 'this' context of type 'aFn | bFn' is not assignable to method's 'this' of type '(this: "hello", args_0: string) => string'.
  Type 'bFn' is not assignable to type '(this: "hello", args_0: string) => string'.
    Type 'Promise<string>' is not assignable to type 'string'.

example.ts(9,12): error TS2684: The 'this' context of type 'aFn | bFn' is not assignable to method's 'this' of type '(this: "hello", value: string) => string'.
  Type 'bFn' is not assignable to type '(this: "hello", value: string) => string'.
    Type 'Promise<string>' is not assignable to type 'string'.

example.ts(13,12): error TS2769: No overload matches this call.
  Overload 1 of 6, '(this: (this: "hello", arg0: "world") => string, thisArg: "hello", arg0: "world"): () => string', gave the following error.
    The 'this' context of type 'aFn | bFn' is not assignable to method's 'this' of type '(this: "hello", arg0: "world") => string'.
      Type 'bFn' is not assignable to type '(this: "hello", arg0: "world") => string'.
        Type 'Promise<string>' is not assignable to type 'string'.
  Overload 2 of 6, '(this: (this: "hello", ...args: "world"[]) => string, thisArg: "hello", ...args: "world"[]): (...args: "world"[]) => string', gave the following error.
    The 'this' context of type 'aFn | bFn' is not assignable to method's 'this' of type '(this: "hello", ...args: "world"[]) => string'.
      Type 'bFn' is not assignable to type '(this: "hello", ...args: "world"[]) => string'.
        Type 'Promise<string>' is not assignable to type 'string'.
```

**Playground Link:** <!-- A link to a TypeScript Playground "Share" link which demonstrates this behavior -->
https://www.typescriptlang.org/play/index.html?ssl=30&ssc=2&pln=1&pc=1#code/PTAEBcAsFMGdtNAHgQwLYAcA2dQBMB7UAOwPFAHcCAnAawChwBPDBFAMWNAF5QAKKAEtYALlCxw1QcQDmAGlAA3FFgCu0MRKmyAlDwB84ydJkBuRiwQAjTj35DRR7fKUr1m47oOgACtQJowtAAPFom+ub0AGaqxADG4IIEXHEqWJx8qVhYVihxtGIcXAA+oDbEOmJ+AUGhnjKGpWGyoADe9KCdoNTQ4KrUKWm5+QB0WVh8AEQw2QSTCpNU1Fh4kzrmAL700bEJSVwoGNhMGePDBaBFoKXllb7+gfB1zo1OJm0dXT19A6BnebQRodjlMZlg5goANqLGgrSYAXXW9C2O3iiWSZWkeFOQwBhVsN04dz4em4hmqjxCzQa1zeLXaXW6vX6g2y5xGVixoOgs3moBhy1WSJRIAgMHgiFQmBw+CISwYzFYf1svAEkGEHmcCmUag0dJkpMM1NpFNq1Ii2xiaP2fzSnAAjJlcfkxHEiVUHmb6q9jQyvszfv9RuNubyFks4cLLbt0QcjlgTsRHUGLm6Kh6ak9zbTfZ9Ot8Wba2QCgfGmKHwXzoRHVojNtHrRjOcRsUmncWXcr0-xDfdM1TvTn6h9GQXA87Ac28BWIfya2tNkA

**Related Issues:** <!-- Did you find other bugs that looked similar? -->
- https://github.com/microsoft/TypeScript/pull/27028
- https://github.com/microsoft/TypeScript/issues/29312
- https://github.com/microsoft/TypeScript/pull/30520