Repository: TypeScript
Issue: Generics are lost during `Function.prototype.bind()` and `Function.prototype.call()`
Labels: Suggestion,Awaiting More Feedback

# Suggestion

<!--
  Please fill in each section completely. Thank you!
-->

## 🔍 Search Terms

<!--
  💡 Did you know? TypeScript has over 2,000 open suggestions!
  🔎 Please search thoroughly before logging new feature requests as most common ideas already have a proposal in progress.
  The "Common Feature Requests" section of the FAQ lists many popular requests: https://github.com/Microsoft/TypeScript/wiki/FAQ#common-feature-requests

  Replace the text below:
-->

generic, bind, call

## ✅ Viability Checklist

<!--
   Suggestions that don't meet all these criteria are very, very unlikely to be accepted.
   We always recommend reviewing the TypeScript design goals before investing time writing
   a proposal for ideas outside the scope of the project.
-->
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, new syntax sugar for JS, etc.)
* [x] This feature would agree with the rest of [TypeScript's Design Goals](https://github.com/Microsoft/TypeScript/wiki/TypeScript-Design-Goals).


## ⭐ Suggestion

<!-- A summary of what you'd like to see added or changed -->

Currently, binding or calling a function loses its generics. Suggestion: Don't lose the generic.

## 📃 Motivating Example

<!--
  If you were announcing this feature in a blog post, what's a short explanation that shows
  a developer why this feature improves the language?
-->


Let's say I have a generic function `getMediaAd`

```ts
export async function getMediaAd<T extends Ad>(
	this: Client,
	params: { locale?: string; media_id: string; format: T['format'] },
) {
	const url = this.cmsUrl(`api/ads/random`, params)
	if (!params.locale) url.searchParams.set('locale', this.locale)
	return this.get<T>(url, this.cmsHeaders())
}
```

This function can obtain multiple types of ad formats, determined by `T`.

I want to put this function inside a Client class to access some client-specific features.

```ts
export class Client {
	getMediaAd = getMediaAd.bind(this)
}
```

However, when I do that, `this.getMediaAd` loses its generic parameter.

Losing the generic parameter means I can't tell it what is `T` supposed to be, like this:

```ts
export async function getMediaBillboardAd(
	this: Client,
	params: { locale?: Intl.UnicodeBCP47LocaleIdentifier; media_id: string },
) {
	return this.getMediaAd<AdBillboard>({ ...params, format: adFormat.billboard })
}
```

Here, `T` is `AdBillboard`. However, `getMediaAd` expects 0 generic parameters.

## 💻 Use Cases

<!--
  What do you want to use this for?
  What shortcomings exist with current approaches?
  What workarounds are you using in the meantime?
-->

I want to use this to create an API wrapper client, but keep the ability to declare functions in different files.