-
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
Can not get return type when util.promisify
an function with overloading definations
#26048
Comments
What I believe is going on here: The compiler tries the overloads of I expect the TypeScript team will consider this behavior a design limitation. There are some workarounds that might get |
util.promisify
a overrided functionutil.promisify
an function with overloading definations
Thank you very much for explaining this problem so clearly and in detail. The So it seems that there's no any workaround for me to get the promisified TResult automatically? |
You should be able to write a namespace declaration that will merge with the original function definition. If you can't get it to work, please post your code and I will take a look if I have time. If you like, you could try to help with grpc/grpc-node#54 to get a better solution. |
Thanks for sending me the link from grpc-node, it's just what I want. I understand that we can write a namespace declaration and merge it with the original function definition. However, if the grpc protocol buffers definition is changed, the namespace declaration have to be changed manually, I feel that's not what I want. So I decided to use the callback right now, and keep eyes on the async/await grpc-node issue. Thanks again for your help! |
Related to this issue, is there any way to iterate over methods overload ? With objects we can do the following : type Foo<T extends {}> = {
[J in keyof T]: MyClass<T[J]>
} If we could do the same thing with methods overloads we could have a |
I took the liberty to ask a StackOverflow question about my last comment. Titian Cernicova-Dragomir gave a nice example on how to use these to make Anyway here's the thing: export type Callback<T> = (err: Error | null, reply: T) => void;
// prettier-ignore
export type PromisifyOne<T extends any[]> =
T extends [Callback<infer U>?] ? () => Promise<U> :
T extends [infer T1, Callback<infer P>?] ? (arg1: T1) => Promise<P> :
T extends [infer T1, infer T2, Callback<infer U>?] ? (arg1: T1, arg2: T2) => Promise<U> :
T extends [infer T1, infer T2, infer T3, Callback<infer U>?]? (arg1: T1, arg2: T2, arg3: T3) => Promise<U> :
T extends [infer T1, infer T2, infer T3, infer T4, Callback<infer U>?] ? (arg1: T1, arg2: T2, arg3: T3, arg4: T4) => Promise<U> :
never;
// prettier-ignore
export type GetOverloadArgs<T> =
T extends {
(...o: infer U) : void,
(...o: infer U2) : void,
(...o: infer U3) : void,
(...o: infer U4) : void,
(...o: infer U5) : void,
(...o: infer U6) : void,
(...o: infer U7) : void
} ? U | U2 | U3 | U4 | U5 | U6 | U7:
T extends {
(...o: infer U) : void,
(...o: infer U2) : void,
(...o: infer U3) : void,
(...o: infer U4) : void,
(...o: infer U5) : void,
(...o: infer U6) : void,
} ? U | U2 | U3 | U4 | U5 | U6:
T extends {
(...o: infer U) : void,
(...o: infer U2) : void,
(...o: infer U3) : void,
(...o: infer U4) : void,
(...o: infer U5) : void,
} ? U | U2 | U3 | U4 | U5:
T extends {
(...o: infer U) : void,
(...o: infer U2) : void,
(...o: infer U3) : void,
(...o: infer U4) : void,
} ? U | U2 | U3 | U4 :
T extends {
(...o: infer U) : void,
(...o: infer U2) : void,
(...o: infer U3) : void,
} ? U | U2 | U3 :
T extends {
(...o: infer U) : void,
(...o: infer U2) : void,
} ? U | U2 :
T extends {
(...o: infer U) : void,
} ? U :
never;
// prettier-ignore
type UnionToIntersection<U> = (U extends any ? (k: U)=>void : never) extends ((k: infer I)=>void) ? I : never which you can then uses with export type Promisify<T> = UnionToIntersection<
PromisifyOne<GetOverloadArgs<T>>
>;
export type PromisifyAll<T extends {}> = { [J in keyof T]: Promisify<T[J]> }; |
That's awesome, and it's what I want. Seems TypeScript 3.0 has some cool new features and worth to a upgrade. I had given him a +1, and what's in my mind right now is: Could we use some technic to extend the promisify definition comes with the node types under this TypeScript 3.0 new feature? Because it seems not possible to update the @types/node because it's not compatible with old ts version? |
You can do the following: declare module 'util' {
function promisify<T>(fn: T): Promisify<T>;
} |
Thank you so much for your code. I had just tried and get the following error (with [email protected])
Did you get it work in your vscode, and if so, would you like to share a complete defination code so that I could compare it with mine? Thanks again! |
Oops, I had set After switch to TypeScript 3.0, your code work like a charm! Good job buddy, really appreciate it! |
I found another solution before seeing this thread. In the case of grpc generated typescript, the order of the overloaded function is guaranteed to be consistent and the last overloaded function signature is the one get used for export type Promisify<T> = {
[K in keyof T]: T[K] extends (req: infer U, b: any, c: any, callback: (e: any, r: infer V) => void) => any
? (r: U) => Promise<V>
: never
};
// usage
export type IYourServiceClientStub = Promisify<IYourServiceClient>;
|
This issue has been marked as 'Question' and has seen no recent activity. It has been automatically closed for house-keeping purposes. If you're still waiting on a response, questions are usually better suited to stackoverflow. |
TypeScript Version: 3.1.0-dev.201xxxxx
Search Terms:
Code
Expected behavior:
func
's type should beconst func: (arg1: string) => Promise<number>
Actual behavior:
func
's type isconst func: (arg1: string) => Promise<{}>
Promise<{}>
should bePromise<number>
Playground Link:
Related Issues:
The text was updated successfully, but these errors were encountered: