Search code examples
angulartypescriptangular-reactive-forms

not understanding 'No overload matches this call' error


I have been making an weather app following Angular for Enterprise-Ready Web Applications - Second Edition book and am implementing the search component for the app to display weather by the searched city. But, am getting above mentioned error on 'city-search' component.ts file. full error is :

No overload matches this call. Overload 1 of 2, '(observerOrNext?: Partial<Observer<string | null>> | ((value: string | null) => void) | undefined): Subscription', gave the following error. Argument of type '(searchValue: string) => void' is not assignable to parameter of type 'Partial<Observer<string | null>> | ((value: string | null) => void) | undefined'. Type '(searchValue: string) => void' is not assignable to type '(value: string | null) => void'. Types of parameters 'searchValue' and 'value' are incompatible. Type 'string | null' is not assignable to type 'string'. Type 'null' is not assignable to type 'string'. Overload 2 of 2, '(next?: ((value: string | null) => void) | null | undefined, error?: ((error: any) => void) | null | undefined, complete?: (() => void) | null | undefined): Subscription', gave the following error.

city-search.component.ts:

import { Component, EventEmitter, OnInit, Output } from '@angular/core';
import { FormControl, Validators } from '@angular/forms';
import { debounceTime } from 'rxjs/operators';

import { WeatherService } from '../weather/weather.service';

@Component({
  selector: 'app-city-search',
  templateUrl: './city-search.component.html',
  styleUrls: ['./city-search.component.css']
})
export class CitySearchComponent implements OnInit {
  @Output() searchEvent = new EventEmitter<string>()
  search = new FormControl('', [Validators.minLength(2)])

  constructor(private weatherService: WeatherService){}
  ngOnInit(): void {
    this.search.valueChanges.pipe(debounceTime(1000)).subscribe((searchValue: string) => {
      if (!this.search.invalid) {
        this.searchEvent.emit(searchValue)
        const userInput = searchValue.split(',').map(s => s.trim())
      this.weatherService.getCurrentWeather(
        userInput[0],
        userInput.length > 1 ? userInput[1] : undefined
      ).subscribe(data => (console.log(data)))
    }
  })
}
}

I am providing the git link you can find the project there: https://github.com/soorajKADAM/local-weather-app.git

I did not understand what the error means,


Solution

  • The error tells you that there is a type mismatch. When tracing down the error, you can see that the valueChanges Observable is defined to push values of the shape string | null. This is because by default, a reactive form control is nullable, see the docs. However, in your code you only expect a searchValue of type string, you don't handle the possibility of it being null.

    There are two possibilities to fix it:

    Add null to type definition

    The first solution is to extend the type of searchValue to also allow null. To properly handle the null case, I added a check to the existing if statement. Updated code:

    this.search.valueChanges
      .pipe(debounceTime(1000))
      .subscribe((searchValue: string | null) => {
        if (searchValue !== null && !this.search.invalid) {
          // further code...
        }
      });
    

    Define the form control as non-nullable

    In case your form control should not be nullable, you can define it as such like the following:

    search = new FormControl('', {
      nonNullable: true,
      validators: [Validators.minLength(2)]
    });