Home > Software design >  Angular: Property 'next' does not exist on type 'this[keyof this]'
Angular: Property 'next' does not exist on type 'this[keyof this]'

Time:01-31

I'm trying to make my code a little denser by using a variable in order refer the component object (this). The goal is to assign .next value to one of the subjects that I have defined earlier to the component object.

Instead of building correctly I'm getting the error in the title:

"Property 'next' does not exist on type 'this[keyof this]'."

Here is my component:

import { Component, OnInit, Input,ViewChild } from '@angular/core';
import { NgbAlert, NgbAlertModule } from '@ng-bootstrap/ng-bootstrap';
import { Subject } from 'rxjs';
import { debounceTime } from 'rxjs/operators';
import { NgIf } from '@angular/common';

@Component({
  selector: 'app-common-alert',
  templateUrl: './common-alert.component.html',
  styleUrls: ['./common-alert.component.css']
})
export class CommonAlertComponent implements OnInit {

  @Input() res = {};

  private _success = new Subject<string>();
  private _warning = new Subject<string>();
  private _failed = new Subject<string>();
  successMessage = '';
  warningMessage = '';
  failedMessage = '';

  @ViewChild('staticAlert', { static: false }) staticAlert: NgbAlert | undefined;
  @ViewChild('selfClosingAlert', { static: false }) selfClosingAlert: NgbAlert | undefined;

  ngOnInit(): void {
    console.log(this);
    this._success.subscribe(message => this.successMessage = message);
    this._success.pipe(debounceTime(3000)).subscribe(() => {
      if (this.selfClosingAlert) {
        this.selfClosingAlert.close();
      }
    });

    this._warning.subscribe(message => this.warningMessage = message);
    this._warning.pipe(debounceTime(3000)).subscribe(() => {
      if (this.selfClosingAlert) {
        this.selfClosingAlert.close();
      }
    });

    this._failed.subscribe(message => this.failedMessage = message);
    this._failed.pipe(debounceTime(3000)).subscribe(() => {
      if (this.selfClosingAlert) {
        this.selfClosingAlert.close();
      }
    });

  }

  
  public changeResultMessage(event: any) {
    this[event.type as keyof typeof this].next(event.message); //this here is the line giving the error
  }

  close(alert: any) {
    this.alerts.splice(this.alerts.indexOf(alert), 1);
  }
}

I could use if else clause, but in that case I'd have to create a block for each individual subject and although it wouldn't be much work I'd still like to know how to do it this way in angular.

Thanks in advance for your tips

CodePudding user response:

You're relying on an as assertion to cast event.type to keyof typeof this, but there are a number of properties in this that are not Subjects, and therefore don't have a next() function.

The cleanest way to solve this would be to properly define your types, for example:

type AlertType = '_success' | '_warning' | '_failed';

interface Alert {
  type: AlertType;
  message: string;
}

class Component {
  private _alerts: { [type in AlertType]: Subject<string> } = {
    _success: new Subject<string>(),
    _warning: new Subject<string>(),
    _failed: new Subject<string>()
  };

  public changeResultMessage(alert: Alert) {
    this._alerts[alert.type].next(alert.message);
  }
}
  • Related