Home > other >  Type 'void' is not assignable to type 'Subscription'
Type 'void' is not assignable to type 'Subscription'

Time:06-16

After upgrading my project from Angular 11 to 12, rxjs from 6.6.6 to 7.1.0 and Typescript from 3.9.7 to 4.0.2, I'm getting the following error related to my timer subscription:

material-input.component.ts:1262:7 - error TS2322: Type 'void' is not assignable to type 'Subscription'. 1262 this.onBlurTimerSubscription = timer(ALLOW_PRIORITY_OPTION_SELECTED_DELAY).subscribe(() => {

The timer is in the onBlur handler below:

onBlurTimerSubscription: Subscription;
// Below works to resolve the error. Is it ok?
// onBlurTimerSubscription: Subscription | any; 

onBlur(event: any) {
  this.allowOnChangeEvent = true;
  this.cleanupUnmatchedError();
  this.allowApiCalls = false;
  this.hasFocus = false;
  if (this.autoCompleteDisabled) {
    this.onBlurComplete(event);
  } else {
    /**
     * NOTE - Need to prioritize the `optionSelected` event over blur.
     *        Since the `onChange` event is debounced, if blur fires first
     *        theres a chance it won't execute properly.
     */
    const ALLOW_PRIORITY_OPTION_SELECTED_DELAY = 10   this.debounceCustomEventDelay;
    this.onBlurTimerSubscription = timer(ALLOW_PRIORITY_OPTION_SELECTED_DELAY).subscribe(() => {
      this.onBlurComplete(event);
    }).add(() => {
      safeUnsubscribe(this.onBlurTimerSubscription);
    });
  }
}

This code has worked without issue prior to the updates mentioned above. What steps do I need to take to refactor for the error?

CodePudding user response:

You can solve this in different ways:

Create a private class property of type Subscription, store the subscription and in ngOnDestroy life cycle hook, unsubscribe to it:

...
export class Component implements OnDestroy {
  private mySub = new Subscription();

  inSomeFunction() {
    // like this or
    this.mySub = timer(ALLOW_PRIORITY_OPTION_SELECTED_DELAY)
     .subscribe(() => this.onBlurComplete(event))

    // like this
    // this works better if you want to handle multiple
    // subscriptions, you just add them
    this.mySub.add(
      timer(ALLOW_PRIORITY_OPTION_SELECTED_DELAY)
       .subscribe(() => this.onBlurComplete(event))
    );
  }

  ngOnDestroy(): void {
    this.mySub?.unsubscribe(); // don't forget the ? operator
  }
}

Or you can managed the subscription with a Subject:

...
export class Component implements OnDestroy {
  private ngSubscription = new Subject();

  inSomeFunction() {
    timer(ALLOW_PRIORITY_OPTION_SELECTED_DELAY)
     .pipe(takeUnitl(this.ngSubscription))
     .subscribe(() => this.onBlurComplete(event))
  }

  ngOnDestroy(): void {
    this.ngSubscription.next();
    this.ngSubscription.complete();
  }
}
  • Related