-
Notifications
You must be signed in to change notification settings - Fork 12.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Generics are lost during Function.prototype.bind()
and Function.prototype.call()
#54707
Comments
If we're being honest here, you guys are frighteningly smarter than me. I get lost literally five words in in any of these discussions. Basically, what I want is for the bound function to have the same signature (including generics) as the original function. I have a minimal reproduction sample here: type AdType = 'banner' | 'billboard'
interface BaseAd {
type: AdType
}
interface BillboardAd extends BaseAd {
type: 'billboard'
}
interface BannerAd extends BaseAd {
type: 'banner'
}
type Ad = BannerAd | BillboardAd
/**
* > function getAd<T extends Ad>(this: Client, type: T['type']): T
*/
function getAd<T extends Ad>(this: Client, type: T['type']): T {
return this.get<T>({ type })
}
class Client {
/**
* > (property) Client.getAd: (type: "banner" | "billboard") => Ad
*
* This type is incorrect; it should be:
* ```ts
* (property) Client.getAd: <T extends Ad>(this: Client, type: T['type']): T
* ```
*/
getAd = getAd.bind(this)
getBannerAd = getBannerAd.bind(this)
getBillboardAd = getBillboardAd.bind(this)
protected get<O>(input: unknown): O {
// Network request or something...
return input as O
}
}
function getBannerAd(this: Client): BannerAd {
// Type 'Ad' is not assignable to type 'BannerAd'.
// Type 'BillboardAd' is not assignable to type 'BannerAd'.
// Types of property 'type' are incompatible.
// Type '"billboard"' is not assignable to type '"banner"'.
return this.getAd<BannerAd>('banner')
}
function getBillboardAd(this: Client): BillboardAd {
// Expected 0 type arguments, but got 1.
return this.getAd<BillboardAd>('billboard')
} In this example, |
I posted a related question on stackoverflow and it looks like there's no current option to solve it: https://stackoverflow.com/questions/76924554/why-doesnt-typescript-correctly-infer-this-type |
One thing to keep in mind is that the declare const timeout: number;
declare function toTuple<T, U>(a: T, b: U): [T, U];
const tupleWithFoo = toTuple.bind(undefined, timeout);
// Expected type : (b: U) => [number, U] |
Suggestion
π Search Terms
generic, bind, call
β Viability Checklist
My suggestion meets these guidelines:
β Suggestion
Currently, binding or calling a function loses its generics. Suggestion: Don't lose the generic.
π Motivating Example
Let's say I have a generic function
getMediaAd
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.
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:Here,
T
isAdBillboard
. However,getMediaAd
expects 0 generic parameters.π» Use Cases
I want to use this to create an API wrapper client, but keep the ability to declare functions in different files.
The text was updated successfully, but these errors were encountered: