Daniel
Daniel

Reputation: 67

Typescript callback with variable parameters undefined

I having trouble to pass multiple parameters through a callback function. For some reason is one of the objects undefined.

How do i define a callback functions with multiple parameters ?

  public save() {
    let oldStartDate = "2019-01-01";

    let newProject = new Project();
    newProject.oldStartDate = "2018-01-01";

    this.doSomeWork(newProject, this.workFinished_Callback.bind(this), oldStartDate);
  }

  public doSomeWork(project:Project, callback: (updatedProject: Project, ...param: any[]) => any = null, ...callbackArgs: any[]) {
    //Work work..
    console.log(project); //This exists..

    callback.call(project, ...callbackArgs);
  }

  public workFinished_Callback(project:Project, oldStartDate: string) {
    console.log(project); //This is undefined..
    console.log(oldStartDate); //Shows 2018-01-01
  }

Upvotes: 4

Views: 2279

Answers (1)

Titian Cernicova-Dragomir
Titian Cernicova-Dragomir

Reputation: 249996

The problem is how you use call. The first argument to call is the this parameter passed to the function, which since you bind the callback will not be accessible in the callback. You can pass null as the first argument and pass the project as the second argument and spread the rest of the arguments as the other arguments:

callback.call(null, project, ...callbackArgs);

A better approach would be to not use call. You can just call the function as you normally would:

callback(project, ...callbackArgs);

You can also build a fully type safe version of your code. In 3.2 bind is correctly typed if you enable strictBindCallApply (read PR). This means that we can use bind and get a correctly typed function. Pair this with tuples in rest parameters (PR) and we can get the compiler to check things fully for us:

class Project { oldStartDate!: string }
type DoSomeworkCallbackArgs<T extends (updatedProject: Project, ...param: any[]) => any> =
    T extends (updatedProject: Project, ...param: infer A) => any ? A : []
class DD {
    public save() {
        let oldStartDate = "2019-01-01";

        let newProject = new Project();
        newProject.oldStartDate = "2018-01-01";

        this.doSomeWork(newProject, this.workFinished_Callback.bind(this), oldStartDate);
        this.doSomeWork(newProject, this.workFinished_Callback.bind(this), 0); //error
    }

    public doSomeWork<T extends null | ((updatedProject: Project, ...param: any[]) => any)>(project: Project, callback: T = null, ...callbackArgs: DoSomeworkCallbackArgs<T>) {
        //Work work..
        console.log(project); //This exists..
        if (callback) callback(project, ...callbackArgs);
    }

    public workFinished_Callback(project: Project, oldStartDate: string) {
        console.log(project); // ok now
        console.log(oldStartDate); //Shows 2018-01-01

    }
}


new DD().save()

Upvotes: 3

Related Questions