-
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
Polymorphic this in static methods is not resolving correctly #58492
Comments
Are you sure this has anything to do with static methods? Or is it just declaration merging? Right now you're mucking with existing types. If you rewrite this to be standalone like interface Ctor<T> {
prototype: T;
}
type InferCtorType<T> = T extends Ctor<infer R> ? R : never;
interface MyPromiseConstructor {
withResolvers<T>(): PromiseWithResolvers<T, this>;
new <T>(executor: (resolve: (value: T | PromiseLike<T>) => void, reject: (reason?: any) => void) => void): MyPromise<T>;
}
interface MyPromise<T> {
withResolvers<T>(): PromiseWithResolvers<T, Ctor<this>>;
}
declare var MyPromise: MyPromiseConstructor;
interface PromiseWithResolvers<T, TCtor = Ctor<MyPromise<T>>> {
promise: InferCtorType<TCtor>;
resolve(value: T): void;
reject(reason: unknown): void;
}
class CustomPromise<T> extends MyPromise<T> {
custom() { }
}
CustomPromise.withResolvers().promise.custom();
new CustomPromise(() => null).withResolvers().promise.custom(); Playground link |
The whole point of having a polymorphic Promise.withResolvers<void>(); // Must return resolver with Promise<void>
MyCustomPromise.withResolvers<void>(); // Also must return resolver with MyCustomPromise<void> and not Promise<void> assuming that MyCustomPromise extends Promise of course It does not matter if it's trying to extend existing API - it does not work in custom APIs as well. If you do not like the example I provided, which is btw a real case example of the type that I tried to fix in the latest TS which does not respect polymorphic behavior of the UPDATE: Also your example is broken and actual return type of the static method is This error happens due to the way custom type is constructed and inference of the constructor was not able to get the instance level type, once we fix the constructor we see the same bug as in my examples above: UPDATE 2: The bug is essentially in the resolution of |
I'm not a TS team member so you don't have to necessarily do anything for my sake, but it definitely helps to have a standalone example that doesn't worry about merging. Real world examples are great for showing use cases, self-contained ones are better for debugging. Anyway, thanks for the updated example. I'm still not sure if they're going to consider this a bug or not. But, for what it's worth: the workaround from #5863 might work here, too, where you use a interface MyPromiseConstructor {
withResolvers<T, Th extends MyPromiseConstructor>(this: Th): PromiseWithResolvers<T, Th>;
} |
A workaround only masks the bug really and does not solve the problem. I cannot see how this is not a bug really, TS is simply breaking down in "static-level" polymorphism scenario and behaves inconsistently with it's "instance-level" polymorphism which works properly. What can we do to convince TS members that this is in fact a bug so that it gets fixed? |
You can do this, you just need a site-specific interface PromiseConstructor {
withResolvers<T, U>(this: U): PromiseWithResolvers<T, U>;
} This works as desired |
@RyanCavanaugh I know that you can "workaround" this issue by adding CustomPromise.withResolvers<string, CustomPromise<string>(); // Users are forced to write full type in generic as a "workaround"
CustomPromise.withResolvers() as CustomPromise<string>; // So generics in such API are useless as simple typecast is simpler
CustomPromise.withResolvers<string>(); // And this is the goal - return type must be CustomPromise<string> if this issue would get resolved The problem with this static case is that this behavior properly works in non-static use-case and you do not need this kind of workarounds there, hence I see this as a bug because it does not behave in the same way in static context. Don't you think that |
This isn't a crash, it isn't unsound, it isn't something that can't be accomplished via some means -- it's a feature request. I want TypeScript to have all the good features it can, but it doesn't yet. |
It is not critical yes as you said it does not crash compiler, but I would say it is unsound, or maybe more precisely - it's inconsistent with it's instance level behavior. Also I would not call this a feature request, as it does not require anything new to be added but rather fix existing behavior to align static level with instance level behavior imho. |
If it turns out #5863 can be implemented straightforwardly with little or no associated costs, it seems likely we'd accept that PR |
Great! Maybe I will find time at some point in the future to try to figure it out. EDIT: Btw if you could point out which file(s) to look into to fix this issue, that would greatly help me (or somebody else) to potentially come up with a fix PR π |
π Search Terms
polymorphic this in static methods
π Version & Regression Information
β― Playground Link
https://www.typescriptlang.org/play/?#code/JYOwLgpgTgZghgYwgAgMJgPZQDwBUB8yA3gFDLnIAOUGmYAnpRAFzK4DcJAviQ08gEkQMaOiy5GEPIQC8bZBAAekEABMAzmkw5QIqMgBKhAPyHkrEBABu0TiRIB6B20nqSoSLEQoACjQC2wOoQqBgg6mBQAK4I2sRkFADuwGAAFgYQ6hgANjZQ6tIAFACUrH4YgcEA6inpmTl5BbgANMhpQficPO7g0PBIyOWVUgTxFMjJaRlZudBN+CVlAUEQNVP1s-l4rWI47er4ndz2Hn3eg8vVtdMNc9tsu8hyu9hDK9KHYxTUFSusQnpdhImHhdkdxlANjZClY4Nkoiw2KVkFYMMBVJwIRAAFYQWKFSFwLIgVhREAAaxAGESIGRqPRXXsCGyRM0qCiEQqb2C0gUyggak03JGhFI4wQHMw-hKxGQPG6TmQAFFFHB-JRshASOzOf5hQA6SZ1GaNEr6n7DfUS3UldjIRXYAC0juQAFUAHJKgAaPiVqFwSoAIhdfsFQuFIjE4i7-JLkAAjFB8CAYGBoSVcy5ayyJdO64WFGUyQggKLZbLFQ3XKFzM0WlZWjPS4p2h3O5BVLDkzRhZCgCJwEADfwQNIYDQkIA
π» Code
π Actual behavior
Polymorphic "this" in static methods is not resolved to actual type but instead resolves to definition time type.
π Expected behavior
Polymorphic "this" in static methods must resolve to proper subclass depending on the invocation.
Additional information about the issue
There was a similar bug reported #5863 but it is not talking specifically about the "this" type keyword which has the bug.
The text was updated successfully, but these errors were encountered: