Repository: TypeScript
Issue: Inconsistent errors reported between tsc and VSCode (Unions across objects with method overload definitions)
Labels: Bug,Help Wanted,Cursed?

# Bug Report

This is similar to #52813, in spirit. However the errors, how it's reproduced, and the code causing it are pretty different. 

Basically I have a code snippet that appears 100% error-free* (most of the time, see note below) in the VSCode IDE. Logically in my head the code should be error free too. However, when I run `tsc` I get an error inside the snippet.

Here's the code:
```ts
export function createWebGLContext(
  canvas: HTMLCanvasElement | OffscreenCanvas,
): WebGLRenderingContext | null {
  return (
    canvas.getContext('webgl')
  )
}
```

`tsc` reports this error:
```
createWebGLContext.ts:4:3 - error TS2322: Type 'RenderingContext | null' is not assignable to type 'WebGLRenderingContext | null'.
  Type 'CanvasRenderingContext2D' is missing the following properties from type 'WebGLRenderingContext': drawingBufferHeight, drawingBufferWidth, activeTexture, attachShader, and 428 more.

4   return (
    ~~~~~~~~
5     canvas.getContext('webgl')
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
6   )
  ~~~
```

_\* In the larger project that I originally discovered this issue, I actually do sometimes see the error in the IDE. I haven't figured out how to consistently cause it, but restarting the TS server or making a small change and saving the file generally clears the error._

### 🔎 Search Terms

inconsistency, inconsistent, errors, ts language server, tsc

### 🕗 Version & Regression Information

- Attempted on 5.0.3 and latest dev build (typescript@5.1.0-dev.20230331)

### ⏯ Playground Link 

With the Playground, since it uses elements of VSCode under the hood, the snippet appears valid with no errors.
[Playground link with relevant code](https://www.typescriptlang.org/play?ts=5.0.3#code/KYDwDg9gTgLgBAMwK4DsDGMCWEVzVYAQxmAHVgAjAcQBkBhHEkGACgFgAoOPQlAN0IBnAFxwAEgBUAsvV4DBAUQA2wALbAU8AD5wA8ggSD8wDXTlCANJwCUo8tRoAlDQBNgUTCgDmDTaG1wKEhKSnAA3pzcBDBIULjsXNw8-EIAdF7AML5MrADkAO6UXkq51pFwZRwAvpxAA)

You can also clone this repo or start a Github CodeSpace on it to reproduce the errors when running `tsc`:
https://github.com/frank-weindel/ts-53614-ide-tsc-inconsistency

### 🙁 Actual behavior

- `tsc` considers the above code to have an error. 
- VSCode normally and properly does not show that error, but it occasionally can.

### 🙂 Expected behavior

- `tsc` should not consider above code to have an error.
- VSCode should be consistent with `tsc`.

### Analysis

I'm not sure why but this seems related to the use of the union `HTMLCanvasElement | OffscreenCanvas` for the variable `canvas`.

Both interfaces in the union contain a set of method overloads for `getContext`...

**lib.dom.d.ts**
```ts
// ...
interface HTMLCanvasElement extends HTMLElement {
    // ...
    getContext(contextId: "2d", options?: CanvasRenderingContext2DSettings): CanvasRenderingContext2D | null;
    getContext(contextId: "bitmaprenderer", options?: ImageBitmapRenderingContextSettings): ImageBitmapRenderingContext | null;
    getContext(contextId: "webgl", options?: WebGLContextAttributes): WebGLRenderingContext | null;
    getContext(contextId: "webgl2", options?: WebGLContextAttributes): WebGL2RenderingContext | null;
    getContext(contextId: string, options?: any): RenderingContext | null;
    // ...
}
// ...
interface OffscreenCanvas extends EventTarget {
    // ...
    getContext(contextId: "2d", options?: any): OffscreenCanvasRenderingContext2D | null;
    getContext(contextId: "bitmaprenderer", options?: any): ImageBitmapRenderingContext | null;
    getContext(contextId: "webgl", options?: any): WebGLRenderingContext | null;
    getContext(contextId: "webgl2", options?: any): WebGL2RenderingContext | null;
    getContext(contextId: OffscreenRenderingContextId, options?: any): OffscreenRenderingContext | null;
    // ...
}
// ...
```

Based on these method overload signatures I'd expect the statement `canvas.getContext('webgl')` to use the union of these two overrloads:
```
getContext(contextId: "webgl", options?: any): WebGLRenderingContext | null; // from HTMLCanvasElement
getContext(contextId: "webgl", options?: WebGLContextAttributes): WebGLRenderingContext | null; // from OffscreenCanvas
```

Which I believe would reduce down to look like this:
```
getContext(contextId: "webgl", options?: any): WebGLRenderingContext | null;
```

Where the return type is `WebGLRenderingContext | null`. Which is what we see if we hover over the method name in the Playground or VSCode.

However, `tsc` inferred the return type of the method to be `RenderingContext | null`.

`RenderingContext | null` is returned by the base method signature for getContext() in **HTMLCanvasElement**:
```
getContext(contextId: string, options?: any): RenderingContext | null;
```

So it would seem `tsc` somehow is inferring the wrong override while TS Language Server / VSCode is inferring the correct one.