Repository: TypeScript
Issue: Forward compatible type definitions regarding compiler warnings
Labels: Suggestion,Needs Proposal

## Search Terms

forward compatibility, experimental features, forward compatible, undeclared types, new browser features, warning undeclared overloads

## Suggestion

Currently if a TypeScript `.d.ts` file contains a function overload with an unknown type it doesn't discard the type but rather treats it like there was an overload that produces `any` as the return type.

This is more easily demonstrated with an example:

```js
// plus.js
function plus(x, y) {
  return x + y
}
```

```ts
// plus.d.ts
export default function plus(a: number, b: number): number

// Forward compatible definition that should be ignored by older
// versions of TypeScript that don't recognise it or by
// consumers using a "target"/"lib" that isn't "esnext" (or whatever version
// bigint eventually ends up in)
export default function plus(a: bigint, b: bigint): bigint

export default function plus(a: string, b: string): string
```

Now if we use the function like so:

```js
const value = plus({}, {})
```

Will produce different results based on if the `--lib`/`--target` supports `bigint or not.

In a world that does support BigInt we will get a warning: `Argument of type '{}' is not assignable to parameter of type 'string'` which means if people are in the future world then it behaves just fine. But if they use it in a non future world then no warning is issued and the type of `value` is inferred to be `any`.

NOTE: The fact `bigint` is used here isn't really important it was just a simple example to write, this applies to any differences between needed target of the `d.ts` file and target of the consumer.

## Use Cases

The main use case is for libraries that wish to be forward compatible with types that might not be configured in `--lib`/`--target` by feature detection (or by just working in the case of the example).

## Examples

I'm not sure what would be the best way of supporting this, probably another flag like `--warnings-ignore-unrecognized-overloads` or something along those lines.

Alternatively it could also be syntax powered e.g. the above example could become something like this:

```js
export default function plus(a: number, b: number): number
export default function plus(a: string, b: string): string

supports bigint {
  export default function plus(a: bigint, b: bigint): bigint
}
```

---

Some additional non-bigint examples using the `supports` example syntax to show examples of where automatic upgrading could happen:

```ts
export default function sum(iterable: Iterable<number>): number

supports AsyncIterable {
  export default function sum(
    asyncIterable: AsyncIterable<number>,
  ): Promise<number>
}

```

```ts
export default function findElements(node: Element): Array<Element>

supports ShadowRoot {
  export default function findElements(shadowRoot: ShadowRoot): Array<Element>
}
```

```ts
export default function render(canvas: HTMLCanvasElement): void

supports OffscreenCanvas {
  export default function render(canvas: OffscreenCanvas): void
} 
```

## Checklist

My suggestion meets these guidelines:
* [✔] This wouldn't be a breaking change in existing TypeScript / JavaScript code
* [✔] This wouldn't change the runtime behavior of existing JavaScript code
* [✔] This could be implemented without emitting different JS based on the types of the expressions
* [✔] This isn't a runtime feature (e.g. new expression-level syntax)