What is the proper way to implement `Observable.bindCallback()` in TypeScript?

Currently, I am attempting to transform a google maps direction service into an Observable pattern. Here is an example taken from https://developers.google.com/maps/documentation/javascript/examples/directions-simple:

  function calculateAndDisplayRoute(directionsService, directionsDisplay) {
    directionsService.route({
      origin: document.getElementById('start').value,
      destination: document.getElementById('end').value,
      travelMode: 'DRIVING'
    }, function(response, status) {
      if (status === 'OK') {
        directionsDisplay.setDirections(response);
      } else {
        window.alert('Directions request failed due to ' + status);
      }
    });
  }

I have attempted the following:

import { Observable } from 'rxjs/Observable'; 
...
  // the callback version works
  getRoute (route: any) {
    const defaults = { 'travelMode': 'WALKING' };
    route = Object.assign(defaults, route);
    this._directionsService.route(
      route
      , (res:any, status:string) => {
          if (status == 'OK')
            this.displayRoute(res);
          else
            this.handleError(res)
       })
  }

  // the Observable version doesn't progress past typescript
  getRoute$ (route: any) {
    const defaults = { 'travelMode': 'WALKING' };
    route = Object.assign(defaults, route);
    let route$ = Observable.bindCallback(
      this._directionsService.route
      , (res, status)=>{res, status}
    );
    // TypeScript indicates, "Supplied parameters do not match any signature of call target
    route$( route ).subscribe(
      (resp:any)=>{
        // also, how do I throw an error from the selector func?
        if (resp.status == 'OK')
        this.displayRoute(resp.res);
        else
          this.handleError(resp.res)
      }
    )
  }

Why is TypeScript rejecting this particular pattern?

Answer №1

When facing the same error while using bindCallback, I found a workaround by explicitly stating the type of the variable that points to the result of bindCallback as "any". You can try:

let route$ : any = Observable.bindCallback(...)

However, this approach doesn't offer an explanation for why Typescript rejects it. My theory is that the rejection might be due to the parameterized type definitions for the result of bindCallback (generically typed). Take a look at BoundCallbackObservable.d.ts to see the multiple parameterized definitions for the overloaded "create" methods, one of which is eventually invoked.

Answer №2

If you're working with rxjs 5, the solution to this issue involves adhering to a specific type signature.

static create<T, R>(callbackFunc: (v1: T, callback: (result: R) => any) => any, selector?: void, scheduler?: IScheduler): (v1: T) => Observable<R>;

It's important to note that this function requires two types in order to produce a callback that operates on one parameter of type T and returns an Observable<R>.

How to Use:

type routeType = String

interface returnType = {
  res: any
  status: any
}

let route$: any = Observable.bindCallback<routeType, observableType>(this._directionsService.route, (res, status)=>{res, status})

With this setup, the type of route$ is now

(v1: routeType) => Observable<observableType>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The type x cannot be assigned to the parameter '{ x: any; }'

Currently learning Angular and Typescript but encountering an error. It seems to be related to specifying the type, but I'm unsure of the exact issue. Still new at this, so any guidance is appreciated! src/app/shopping-list-new/shopping-edit/shopp ...

The function Sync in the cp method of fs.default is not a valid function

When attempting to install TurboRepo, I encountered an issue after selecting npm. >>> TURBOREPO >>> Welcome to Turborepo! Let's get you set up with a new codebase. ? Where would you like to create your turborepo? ./my-turborepo ...

Incorporating Close, Minimize, and Maximize functionalities into a React-powered Electron Application

Struggling with implementing minimize, maximize, and close functionality for a custom title bar in an electron app using React Typescript for the UI. The issue lies within the React component WindowControlButton.tsx, as it should trigger actions to manipu ...

Is there a way in NodeJS to preview the contents of a file in a browser before initiating the download process?

Is there a way to preview a file in the browser before downloading it in NodeJS? This would allow users to make sure they are choosing the correct file to download. Currently, I have this code for downloading a file: app.get("/download/file", (req, res) = ...

Troubleshooting: The reason behind my struggles in locating elements through xpath

There is a specific element that I am trying to locate via XPath. It looks like this: <span ng-click="openOrderAddPopup()" class="active g-button-style g-text-button g-padding-5px g-margin-right-10px ng-binding"> <i class=&quo ...

Include a checkbox within a cell of a table while utilizing ngFor to iterate through a two-dimensional array

I am working with a two-dimensional array. var arr = [ { ID: 1, Name: "foo", Email: "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="f5939a9ab5939a9adb969a98">[email protected]</a>", isChecked: "true" ...

What could be causing Angular's Renderer2 to generate inaccurate outcomes?

Having an array of queries with varying positions of underscores: Newtons __________ Law dictates __________ is the result of an object's mass and speed. My goal is to show each question to users, replacing the blanks with in ...

Combining React Context and Typescript using a Custom Hook

I have been working on a context provider in React and Chakra-UI, but I seem to be facing some issues: import { useBoolean } from "@chakra-ui/react" import { createContext } from "react" const MobileContext = createContext<typeof us ...

Troubleshooting: Why the OnPush change detection strategy may not be

Parent.component.html <app-child [activeUser]="activeUser" *ngIf="eceConfirm && activeUser"></app-child> Parent.component.ts During the initialization of the component, the getAllEmployees method is called to fetch ...

There is no overload that fits this call (regarding a basic array retrieved from an api)

While attempting to utilize a .map function on a simple array (['a','b','c']) fetched using the useEffect hook, I encountered an error in TypeScript. The array elements rendered correctly when the code was executed and no erro ...

Ways to invoke external jQuery functions within Angular applications

In the midst of working on an Angular CLI Project, I find myself needing to incorporate some jQuery functionalities. To accomplish this task, I have added the necessary JavaScript files in the angular.json configuration: "scripts": [ "node_modules/jq ...

Angular Material 2 with Customized Moment.js Formatting

Is there a way to display the year, month, day, hours, minutes, and seconds in the input field of my material datepicker? I have successfully customized the parse() and format() methods in my own DateAdapter using native JavaScript objects. Howe ...

An error in TypeScript has occurred, stating that the type 'IterableIterator<any>' is neither an array type nor a string type

Hey there! I'm currently working on an Angular project and encountering an error in my VS Code. I'm a bit stuck on how to fix it. Type 'IterableIterator<any>' is not an array type or a string type. Use compiler option '- ...

Exploring the process of retrieving array data from an API using Ionic 3

I need help accessing array data and displaying it in an ion-select element. html <ion-item> <ion-label>Select Time</ion-label> <ion-select interface ="popover"> <div *ngFor="let item of items"> ...

Upon initializing an Angular project from the ground up, I encountered an issue where a custom pipe I had created was not

After creating an Angular 16.1.0 application and a custom pipe, I encountered error messages during compilation. Here are the steps I took: Ran ng new exampleProject Generated a pipe using ng generate pipe power Modified the content of app.compone ...

Issue with TypeORM @BeforeInsert causing a field in Entity not to be populated with value

Currently, I am facing an issue where I am attempting to update or insert into a token field before the record is saved. However, when utilizing the @BeforeInsert hook, I encounter the following error: "error": "Cannot read property 'co ...

Having trouble with installing Typescript on a MacBook?

I have been attempting to follow the instructions provided on TypeScriptLang.org but for some reason, I am unable to successfully download typescript. This is what I have tried so far: mkotsollariss-MacBook-Pro:/ mkotsollaris$ which node /usr/local/bin/n ...

tips for accessing the useState value once it has been initialized

When using the state hook in my code, I have: const [features, setFeatures] = useState([]) const [medicalProblem, setMedicalProblem] = useState([]) The medicalProblem variable will be initially populated with a response from an API call: useEf ...

A component in Angular is able to inherit properties without the need to duplicate the constructor

I have been searching for a way to enhance the DRYness of my code by creating a solid Component parent. However, inheriting a Component from another Component requires duplicating the constructor(<services>){}, which goes against the DRY principle. T ...

Utilizing class attributes within multiple classes

I have created a custom class called MutationValidator as follows: const ERR_MSG = 'Error1'; @Service() export class MutationValidator { .. } This class is used in another class like so: import { MutationValidator } from './mutation ...