Repository: TypeScript
Issue: Alternate syntax for function overloads
Labels: Suggestion,Awaiting More Feedback

<!-- 🚨 STOP 🚨 𝗦𝗧𝗢𝗣 🚨 𝑺𝑻𝑶𝑷 🚨

Half of all issues filed here are duplicates, answered in the FAQ, or not appropriate for the bug tracker. Please read the FAQ first, especially the "Common Feature Requests" section.

-->

## Search Terms

<!-- List of keywords you searched for before creating this issue. Write them down here so that others can find this suggestion more easily -->
class method signature
method signature
function overload syntax
function overload
proxy function
proxy function signature
## Suggestion

<!-- A summary of what you'd like to see added or changed -->
A new syntax for function overloads:

```js
function Func as FunctionSignature
class A {
  static Func as FunctionSignature
  Func as FunctionSignature
}
```
This would allow types to be less static, and often more accurate to the purpose of the overloaded function

Right now, we can do something similar using `const` -
```js
const: FunctionSignature = function() {}
```
however, the differences in detailed in #25761 and the lack of any  equivalent in classes make this a separate issue.

I'm not dead set on the `as` syntax, but I think it fits with what we already have quite well. The checking done on overloads is similar to that of `({ prop: "HI" } as { prop: number })`, and it fits well in and out of classes

It's also worth noting that every use case of this would benefit greatly from #28172 
## Use Cases

### Generic Types

```js
type Pipe<V> = (val: V) => V
function MyFunc as Pipe<string>
// function MyFunc(val: string): string
function MyFunc(...args: any[]): any {

}
```

### Inheritance

```js
function tryInt as typeof parseInt
// function tryInt(s: string, radix?: number): number
function tryInt(...args: [string, number?]) {
  const n = parseInt(...args)
  if (isNaN(n)) throw "Failed to parse"
  return n
}
```
### Combining function implementations

A solution to the problems brought up in #12041 -

```js
function overload as typeof implementation
function overload as typeof otherImplementation
// function overload(num: number): string
// function overload(str: string, num: number): string
function overload(...args: [string, number] | [number]) {
  return args.length === 1 ? implementation(...args) : otherImplementation(...args)
}

```
Which would work particularly well combined with #28172,
```js
function overload as typeof implementation
function overload as typeof otherImplementation
function overload() {
  return arguments.length === 1 ? implementation(...arguments) : otherImplementation(...arguments)
}
```
fully checking the types against the current signature of both implementations, and emitting useful errors
<!--
What do you want to use this for?
What shortcomings exist with current approaches?
-->

## Examples

<!-- Show how this would be used and what the behavior would be -->
This came up in the context of an argument parser, where I attempt to parse the values using a direct proxy to another method -

```js
class ArgumentIssue {
  confidence: number
}
class Arguments {
  async parse(args: string, cb: (val: string) => any = v => v): Promise<{ [key: string]: any }> {
    // Follows the return value ^
  }
}
class Signature extends Array<Arguments> {
  parse as ArgumentBuilder["parse"]
  // parse(args: string, cb: (val: string) => any): Promise<{ [key: string]: any }>
  parse(a: any, ...args: any[]) {
    let Nearest: [Arguments, ArgumentIssue];
    for (const overload of this) {
      try {
        return overload.parse(a, ...args)
      } catch (issue) {
        if (!(issue instanceof ArgumentIssue)) throw issue;
        if (!Nearest || issue.confidence > Nearest[1].confidence)
          Nearest = [overload, issue];
      }
    }
    throw Nearest;
  }
}
```
## Checklist

My suggestion meets these guidelines:

* [x] This wouldn't be a breaking change in existing TypeScript/JavaScript code
* [x] This wouldn't change the runtime behavior of existing JavaScript code
* [x] This could be implemented without emitting different JS based on the types of the expressions
* [x] This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, etc.)
* [x] This feature would agree with the rest of [TypeScript's Design Goals](https://github.com/Microsoft/TypeScript/wiki/TypeScript-Design-Goals).