Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

BehaviorSubject with Typescript gives error if initialized with null as default value

I have an interface called SelectedNodeInfoInterface. I have a BehaviorSubject which I would like to initialize with null and after some operation completes, or method is called i pass new value (.next(value)) on it. It used to work fine but I enabled

strict:true

in my typescript config and since then it started to give me error. If I disable that flag, it compiles without problem and works as expected. However, I would like to keep strict mode enabled.

Code looks like this

export class SharedLinkedDetailsService {
selectedAccounts$: BehaviorSubject<SelectedNodeInfoInterface>;
constructor() {
  this.selectedAccounts$ = new BehaviorSubject(null);

 }

accountsSelected(selectedNode: SelectedNodeInfoInterface) {
  this.selectedAccounts$.next(selectedNode);
}

export interface SelectedNodeInfoInterface {
  selectedAccounts?: string | string[];
  highlightEdges?: boolean;
 }

Type 'BehaviorSubject' is not assignable to type 'BehaviorSubject'.

Any suggestions will be appreciated.

like image 938
Vatsal Avatar asked Nov 22 '19 05:11

Vatsal


3 Answers

Try this:

export class SharedLinkedDetailsService {
  selectedAccounts$: BehaviorSubject<SelectedAccountType | null>;
  constructor() {
    this.selectedAccounts$ = new BehaviorSubject<SelectedAccountType | null>(null);

  }

  accountsSelected(selectedNode: SelectedNodeInfoInterface) {
    this.selectedAccounts$.next(selectedNode);
  }

The point about strict mode is that null and undefined types are not allowed as alternatives to a defined type. So in that case, if you define a type where the value may also be null or undefined, you have to explicitly declare that possibility. The pipe tells typescript that the type may be either SelectedAccountType or null. I hope that makes it clear!

like image 173
see sharper Avatar answered Oct 04 '22 03:10

see sharper


Try this: Another way to set type

this.selectedAccounts$ = new BehaviorSubject({} as SelectedNodeInfoInterface);

like image 29
Jagdish Chaudhari Avatar answered Oct 04 '22 04:10

Jagdish Chaudhari


You need to type the behavior subject

this.selectedAccounts$ = new BehaviorSubject<SelectedNodeInfoInterface>(null);

or

this.selectedAccounts$ = new BehaviorSubject(null as SelectedNodeInfoInterface);

or

this.selectedAccounts$ = new BehaviorSubject(null) as BehaviorSubject<SelectedNodeInfoInterface>;

All 3 will work but I would go with number 1.

Personally I would not initialise it in the constructor but just assign a new behavior subject to the property directly.

export class SharedLinkedDetailsService {
  selectedAccounts$ = new BehaviorSubject<SelectedNodeInfoInterface>(null);

  accountsSelected(selectedNode: SelectedNodeInfoInterface) {
    this.selectedAccounts$.next(selectedNode);
  }
like image 29
Adrian Brand Avatar answered Oct 04 '22 04:10

Adrian Brand