Skip to content

Unable to infer types from callback in bindCallback function for RxJS #22952

Closed
@benlesh

Description

@benlesh

Currently type inference is unable to provide useful type inference for functions such as RxJS's bindCallback.

I have a PR here (ReactiveX/rxjs#3480) that tries to add overloads to support the desired behavior, but when I test it, it does not infer types properly.

TypeScript Version: @latest as of this moment

Search Terms: callback type inference, wrapping node callbacks, variadic arguments

Code

export function bindCallback(callbackFunc: (callback: () => any) => any, scheduler?: SchedulerLike): () => Observable<void>;
export function bindCallback<R1>(callbackFunc: (callback: (res1: R1) => any) => any, scheduler?: SchedulerLike): () => Observable<R1>;
export function bindCallback<R1, R2>(callbackFunc: (callback: (res1: R1, res2: R2) => any) => any, scheduler?: SchedulerLike): () => Observable<[R1, R2]>;
export function bindCallback<R1, R2, R3>(callbackFunc: (callback: (res1: R1, res2: R2, res3: R3) => any) => any, scheduler?: SchedulerLike): () => Observable<[R1, R2, R3]>;
export function bindCallback<A1>(callbackFunc: (arg1: A1, callback: () => any) => any, scheduler?: SchedulerLike): (arg1: A1) => Observable<void>;
export function bindCallback<A1, R1>(callbackFunc: (arg1: A1, callback: (res1: R1) => any) => any, scheduler?: SchedulerLike): (arg1: A1) => Observable<R1>;
export function bindCallback<A1, R1, R2>(callbackFunc: (arg1: A1, callback: (res1: R1, res2: R2) => any) => any, scheduler?: SchedulerLike): (arg1: A1) => Observable<[R1, R2]>;
export function bindCallback<A1, R1, R2, R3>(callbackFunc: (arg1: A1, callback: (res1: R1, res2: R2, res3: R3) => any) => any, scheduler?: SchedulerLike): (arg1: A1) => Observable<[R1, R2, R3]>;
export function bindCallback<A1, A2>(callbackFunc: (arg1: A1, arg2: A2, callback: () => any) => any, scheduler?: SchedulerLike): (arg1: A1, arg2: A2) => Observable<void>;
export function bindCallback<A1, A2, R1>(callbackFunc: (arg1: A1, arg2: A2, callback: (res1: R1) => any) => any, scheduler?: SchedulerLike): (arg1: A1, arg2: A2) => Observable<R1>;
export function bindCallback<A1, A2, R1, R2>(callbackFunc: (arg1: A1, arg2: A2, callback: (res1: R1, res2: R2) => any) => any, scheduler?: SchedulerLike): (arg1: A1, arg2: A2) => Observable<[R1, R2]>;

function foo(a: number, b: number, callback: (c: string, d: string) => any): any {
   setTimeout(() => callback(a + '!', b + '!');
}

const source = bindCallback(foo)(1, 3);

Expected behavior:

source should be Observable<[string, string]>

Actual behavior:

source is Observable<void>

Playground Link:
https://www.typescriptlang.org/play/#src=interface%20SchedulerLike%20%7B%20%7D%3B%0D%0A%0D%0Ainterface%20Observable%3CT%3E%20%7B%20%7D%3B%0D%0A%0D%0Aexport%20function%20bindCallback(callbackFunc%3A%20(callback%3A%20()%20%3D%3E%20any)%20%3D%3E%20any%2C%20scheduler%3F%3A%20SchedulerLike)%3A%20()%20%3D%3E%20Observable%3Cvoid%3E%3B%0D%0Aexport%20function%20bindCallback%3CR1%3E(callbackFunc%3A%20(callback%3A%20(res1%3A%20R1)%20%3D%3E%20any)%20%3D%3E%20any%2C%20scheduler%3F%3A%20SchedulerLike)%3A%20()%20%3D%3E%20Observable%3CR1%3E%3B%0D%0Aexport%20function%20bindCallback%3CR1%2C%20R2%3E(callbackFunc%3A%20(callback%3A%20(res1%3A%20R1%2C%20res2%3A%20R2)%20%3D%3E%20any)%20%3D%3E%20any%2C%20scheduler%3F%3A%20SchedulerLike)%3A%20()%20%3D%3E%20Observable%3C%5BR1%2C%20R2%5D%3E%3B%0D%0Aexport%20function%20bindCallback%3CR1%2C%20R2%2C%20R3%3E(callbackFunc%3A%20(callback%3A%20(res1%3A%20R1%2C%20res2%3A%20R2%2C%20res3%3A%20R3)%20%3D%3E%20any)%20%3D%3E%20any%2C%20scheduler%3F%3A%20SchedulerLike)%3A%20()%20%3D%3E%20Observable%3C%5BR1%2C%20R2%2C%20R3%5D%3E%3B%0D%0Aexport%20function%20bindCallback%3CA1%3E(callbackFunc%3A%20(arg1%3A%20A1%2C%20callback%3A%20()%20%3D%3E%20any)%20%3D%3E%20any%2C%20scheduler%3F%3A%20SchedulerLike)%3A%20(arg1%3A%20A1)%20%3D%3E%20Observable%3Cvoid%3E%3B%0D%0Aexport%20function%20bindCallback%3CA1%2C%20R1%3E(callbackFunc%3A%20(arg1%3A%20A1%2C%20callback%3A%20(res1%3A%20R1)%20%3D%3E%20any)%20%3D%3E%20any%2C%20scheduler%3F%3A%20SchedulerLike)%3A%20(arg1%3A%20A1)%20%3D%3E%20Observable%3CR1%3E%3B%0D%0Aexport%20function%20bindCallback%3CA1%2C%20R1%2C%20R2%3E(callbackFunc%3A%20(arg1%3A%20A1%2C%20callback%3A%20(res1%3A%20R1%2C%20res2%3A%20R2)%20%3D%3E%20any)%20%3D%3E%20any%2C%20scheduler%3F%3A%20SchedulerLike)%3A%20(arg1%3A%20A1)%20%3D%3E%20Observable%3C%5BR1%2C%20R2%5D%3E%3B%0D%0Aexport%20function%20bindCallback%3CA1%2C%20R1%2C%20R2%2C%20R3%3E(callbackFunc%3A%20(arg1%3A%20A1%2C%20callback%3A%20(res1%3A%20R1%2C%20res2%3A%20R2%2C%20res3%3A%20R3)%20%3D%3E%20any)%20%3D%3E%20any%2C%20scheduler%3F%3A%20SchedulerLike)%3A%20(arg1%3A%20A1)%20%3D%3E%20Observable%3C%5BR1%2C%20R2%2C%20R3%5D%3E%3B%0D%0Aexport%20function%20bindCallback%3CA1%2C%20A2%3E(callbackFunc%3A%20(arg1%3A%20A1%2C%20arg2%3A%20A2%2C%20callback%3A%20()%20%3D%3E%20any)%20%3D%3E%20any%2C%20scheduler%3F%3A%20SchedulerLike)%3A%20(arg1%3A%20A1%2C%20arg2%3A%20A2)%20%3D%3E%20Observable%3Cvoid%3E%3B%0D%0Aexport%20function%20bindCallback%3CA1%2C%20A2%2C%20R1%3E(callbackFunc%3A%20(arg1%3A%20A1%2C%20arg2%3A%20A2%2C%20callback%3A%20(res1%3A%20R1)%20%3D%3E%20any)%20%3D%3E%20any%2C%20scheduler%3F%3A%20SchedulerLike)%3A%20(arg1%3A%20A1%2C%20arg2%3A%20A2)%20%3D%3E%20Observable%3CR1%3E%3B%0D%0Aexport%20function%20bindCallback%3CA1%2C%20A2%2C%20R1%2C%20R2%3E(callbackFunc%3A%20(arg1%3A%20A1%2C%20arg2%3A%20A2%2C%20callback%3A%20(res1%3A%20R1%2C%20res2%3A%20R2)%20%3D%3E%20any)%20%3D%3E%20any%2C%20scheduler%3F%3A%20SchedulerLike)%3A%20(arg1%3A%20A1%2C%20arg2%3A%20A2)%20%3D%3E%20Observable%3C%5BR1%2C%20R2%5D%3E%3B%0D%0Aexport%20function%20bindCallback%3CT%3E(callbackFunc%3A%20Function%2C%0D%0A%20%20scheduler%3F%3A%20SchedulerLike)%3A%20(...args%3A%20any%5B%5D)%20%3D%3E%20Observable%3CT%3E%20%7B%0D%0A%20%20return%20(...args%3A%20any%5B%5D)%20%3D%3E%20%7B%0D%0A%20%20%20%20return%20null%20as%20Observable%3Cany%3E%3B%0D%0A%20%20%7D%0D%0A%7D%0D%0A%0D%0Afunction%20foo(a%3A%20number%2C%20b%3A%20number%2C%20callback%3A%20(c%3A%20string%2C%20d%3A%20string)%20%3D%3E%20any)%3A%20any%20%7B%0D%0A%20%20%20setTimeout(()%20%3D%3E%20callback(a%20%2B%20'!'%2C%20b%20%2B%20'!')%3B%0D%0A%7D%0D%0A%0D%0Aconst%20source%20%3D%20bindCallback(foo)(1%2C%203)%3B

Related Issues:

Metadata

Metadata

Assignees

No one assigned

    Labels

    Needs More InfoThe issue still hasn't been fully clarified

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions