Why wont Typescript let BehaviorSubject take a union type?

Viewed 2488

I believe this problem is purely Typescript related, and just happens to involve the BehaviorSubject in my case.

I know that both these lines:

    const myVariable: string | null = 'string';

and

    const myVariable: string | null = null;

are valid syntax. So along the same lines I have declared this BehavoirSubject:

    const user: BehaviorSubject<User | null> = new BehaviorSubject(
      null
    );

This doesn't work, as this error:

Type 'BehaviorSubject<null>' is not assignable to type 'BehaviorSubject<User | null>'.
  Types of property 'observers' are incompatible.
    Type 'Observer<null>[]' is not assignable to type 'Observer<User | null>[]'.
      Type 'Observer<null>' is not assignable to type 'Observer<User | null>'.
        Type 'User | null' is not assignable to type 'null'.
          Type 'User' is not assignable to type 'null'.ts(2322)

My expectation is that this BehaviorSubject should take either User or null types in this example, but it will seemingly only accept both at the same time as a single expected type, hence this works as a workaround:

const user: BehaviorSubject<User | null> = new BehaviorSubject(
    null as User | null
  );

The types themselves don't seem to matter, "string | null" and "User | string " both throw the same kind of error, so how should this kind of typing actually be done? I'd rather not have to typecast ever.

Thanks in advance :)

1 Answers

By not specifying the type in the constructor, the generic type parameter is inferred to be null, not User | null. The type of the variable (const user) has no bearing on this (the assignment happens after the value construction and only performs a cast if any).

Explicitly specify the type of T:

const user = new BehaviorSubject<User | null>(null);
Related