Maurice
Maurice

Reputation: 7371

TypeScript instanceof not working while method argument is not a plain object

I have a method that is called from two places where the argument type is known. In this method, the incoming argument is checked for both types yet both return false. I don't understand why this is happening. I've read the question someone else posted who had the same issue. But my problem is different because I am not constructing a plain object like he is. The question can be found here:

TypeScript instanceof not working

Here is the method that causes the problem:

  changeUnitOfValueInput(filter){
    console.log((filter === undefined));
    let filterType: string;
    if (filter instanceof HTMLInputElement)
        filterType = (filter as HTMLInputElement).value;
    else if (filter instanceof AdvancedFilter){
      console.log("its in");
        filterType = (filter as AdvancedFilter).advancedFilterSubject;
    }
    else{
      console.log('im out');
       return;
    }
    switch(filterType){
      case AdvancedFilterSubject.GROWTH_TEMPERATURE:{
        this.unitLabel = (this.filterOptionsForm.controls['measureSystem'].value ==='imperial') ? '°F' : '°C';
        break;
      }
      case AdvancedFilterSubject.GROWTH_DAYS:{
        this.unitLabel = 'days'
        break;
      }
      //fall through
      case AdvancedFilterSubject.PLANT_HEIGHT:
      case AdvancedFilterSubject.PLANT_SPACING:
      case AdvancedFilterSubject.ROW_SPACING:
      case AdvancedFilterSubject.SOW_DEPTH:
        this.unitLabel = (this.filterOptionsForm.controls['measureSystem'].value ==='imperial') ? '″' : '㎝';
    }
  }

This method is called in this component method:

  populateFieldsWithSelectedFilterData(existingAdvancedFilter: AdvancedFilter){
    this.changeUnitOfValueInput(existingAdvancedFilter);
    this.filterOptionsForm.controls['filterType'].setValue(existingAdvancedFilter.advancedFilterSubject);
    this.filterOptionsForm.controls['logicalOperator'].setValue(existingAdvancedFilter.logicalOperator);
    this.filterOptionsForm.controls['advancedFilterValue'].setValue(existingAdvancedFilter.filterValue);    
  }

The second place where it gets called is in the frontend (html part):

    <p-dropdown #filterType formControlName = "filterType" placeholder="Filter type" [options]="filterTypesList" (onChange)="changeUnitOfValueInput(filterType)" >
    </p-dropdown>

The method keeps returning prematurely because both instanceof conditions return false. Can anyone tell me what is going on?

EDIT: Heres the definition of filterTypeList that is used in the HTML

  filterTypesList: SelectItem[] = [
    {label:'Minimum temperature', value: AdvancedFilterSubject.GROWTH_TEMPERATURE},
    {label:'Growth days', value: AdvancedFilterSubject.GROWTH_DAYS},
    {label:'Maximum height', value: AdvancedFilterSubject.PLANT_HEIGHT},
    {label:'Row spacing', value: AdvancedFilterSubject.ROW_SPACING},
    {label:'Plant spacing', value: AdvancedFilterSubject.PLANT_SPACING},     
    {label:'Sow depth', value: AdvancedFilterSubject.SOW_DEPTH}  
    ];

Upvotes: 1

Views: 2759

Answers (1)

Explosion Pills
Explosion Pills

Reputation: 191729

In order for instanceof to work, the prototype of the object you're using has to match the constructor function; HTMLInputElement or AdvancedFilter in this case. This won't necessarily be the case depending upon how the AdvancedFilter gets constructed. You may be better off creating a type guard function:

function isAdvancedFilter(possibleAdvancedFilter: any): possibleAdvancedFilter is AdvancedFilter {
  return possibleAdvancedFilter &&
    !!(possibleAdvancedFilter as AdvancedFilter).advancedFilterSubject;
}

You can of course change this function to whatever checks you need to do to ensure that the value can be used as an AdvancedFilter. Then just use isAdvancedFilter(variable) instead of instanceof variable.

Upvotes: 1

Related Questions