angularfilterangular18

No overload matches this call while calling Angular service method


I am trying to call a method defined in my Angular service in my component.

  1. My Angular service method:

    getGadgetDetailById(id: number)
    {
        return this.gadgets.find(gadget => gadget.id === id);
    }
    

    Here 'gadgets' is obviously an array of type 'Gadget'.

  2. Gadget model type:

    export interface Gadget {
        id: number;
        name: string;
        distributor: string;
        description: string;
        price: number;
        available: boolean;
        rating?: number; 
    }
    
  3. I am trying to call the service method in my component as:

    gadget:Gadget|undefined;
    
    gadgetId:any;
    
    ngOnInit(): void {
        this.ar.paramMap.subscribe(params => {
            this.gadgetId=params.get('id');
        });
    
        this.getGadgetDetailById(this.gadgetId);
    }
    
    getGadgetDetailById(id: number)
    {
        this.gadget = this.gService.getGadgetDetailById(id);
    }
    
    
    

I am getting an error on 'next':

No overload matches this call.
  Overload 1 of 2, '(observerOrNext?: Partial<Observer<Gadget | undefined>> | ((value: Gadget | undefined) => void) | undefined): Subscription', gave the following error.

What is it?


Solution

  • Your problem is here:

    ngOnInit(): void {
        this.ar.paramMap.subscribe(params => {
            this.gadgetId=params.get('id');
        });
    
        this.getGadgetDetailById(this.gadgetId);
    }
    

    Because the subscribe callback isn't called immediately, this.getGadgetDetailById(this.gadgetId) is called, then this.gadgetId=params.get('id'); runs. This means that this.gadgetId is undefined at the time thatthis.getGadgetDetailById is run, so you're searching gadgets for a gadget with an undefined id.

    The simple fix is just to move the call to this.getGadgetDetailById into the subscribe callback:

    ngOnInit(): void {
        this.ar.paramMap.subscribe(params => {
            this.gadgetId=params.get('id');
            this.getGadgetDetailById(this.gadgetId);
        });
    }
    

    This kind of just kicks the problem down the road though, since now this.gadget is being assigned asyncronously, so access to this.gadget may fail if it's accessed before it's assigned. If you want to protect against that, you could make this.gadget an Observable as well:

    gadget: Observable<Gadget | undefined>;
    
    ngOnInit(): void {
        this.gadget = this.ar.paramMap.pipe(
            map((params) => this.gService.getGadgetDetailById(params.get('id'))),
        );
    }
    

    Now this.gadget can be subscribed to, and it will definately, always exist (although it will delay emitting a gadget until the paramater subject has fired.