this is my test code:
type Prop<T> = { new(...args: any[]): T } | { (): T }
declare function propTest<T>(t: Prop<T>): T
when i define a class, it will be ok:
class User {}
propTest(User) // User
But when i pass it with native constructors:
propTest(String) // String(not string)
The reason is String
satisfy both call and constructor signature.
So my question is what should i do to get the compiler to infer the native type?
So I take it you'd like T
to be inferred from the callable signature (()=>T
) before it gets inferred from the newable signature (new(...args: any[])=>T
), but the compiler doesn't want to do that for you? I guess the newable signature always takes priority (it doesn't matter if you switch the order of the union constituents).
Luckily, there's a trick to lowering the priority of an inference site, mentioned by @RyanCavanaugh (one of the language maintainers) in a GitHub issue comment:
T & { }
creates a "lower-priority" inference site forT
by design. I would move this from the "definitely don't depend on this" column to the "it's probably going to work for the foreseeable future" column.
So the trick is to intersect something with the empty object type. Let's see if it works:
type Prop<T> = { (): T } | { new(...args: any[]): (T & {}) }
I've put the T & {}
in the newable signature, to try to lower its priority. Here goes: 🤞
propTest(String) // string 🎉
And let's just make sure it still works for User
:
propTest(User) // User
Okay, hope that helps. Good luck!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With