0

The following example fails to compile (on the last two lines) due to the error shown below.

import { Subject } from 'rxjs';

class Example<T> {

  readonly events = new Subject<T>();

  constructor(x: T) { }
}

// ...

let example: Example<unknown>;

// ...

example = new Example('some string');

// ...

example = new Example(123);

Error:

Type 'Example<string>' is not assignable to type 'Example<unknown>'.
  Types of property 'events' are incompatible.
    Type 'Subject<string>' is not assignable to type 'Subject<unknown>'.
      Types of property 'observers' are incompatible.
        Type 'Observer<string>[]' is not assignable to type 'Observer<unknown>[]'.
          Type 'Observer<string>' is not assignable to type 'Observer<unknown>'.
            Type 'unknown' is not assignable to type 'string'.ts(2322)

The project where I am seeing this error is using Typescript version 4.3.5 and RxJs version 6.5.5. The error also only happens if the strict flag is enabled in tsconfig.json.

I don't understand why I am seeing this error. Every line in the error message (except for the last line) doesn't feel like an error to me because it's saying that a concrete type is being assigned to an unknown type, which is a valid assignment. For the last line (Type 'unknown' is not assignable to type 'string'), I understand that assigning unknown to string would be an error, but I can't see where such an assignment is happening.

What is the issue with the code example?

Edit

I also noted that the error goes away if I remove the events property in the Example class.

Sam Herrmann
  • 6,293
  • 4
  • 31
  • 50
  • You're typing it yourself as unknown with this line `let example: Example; `. Just change the `unknown` to `string` – Marty Sep 22 '21 at 16:12
  • Note that this is a narrowed down example. I can't change `unknown` to `string` because other parts of the code may assign an `Example` of a different type to `example`. I edited my question to make that clearer. – Sam Herrmann Sep 22 '21 at 16:24

1 Answers1

1

It is having an issue because your example variable is type unknown.

The unknown type is only assignable to the any type and the unknown type itself. See more details here.

Use any instead of unknown as a type for your let example: Example<unknown>;.

So it should be:

let example: Example<any>;.

To know more about the differences of the two, you can read a lot of samples from here.

dom.macs
  • 776
  • 7
  • 15
  • Thank you for your help! Where in the code are you suggesting that I am assigning unknown to some other type? From what I can see I am only assigning `Example` and `Example` to `Example`, not the other way around. Any type can be assigned to `unknown`. – Sam Herrmann Sep 24 '21 at 15:23
  • You are using strict: true. It is true that any type can be assigned to unknown, but in your scenario, you enabled strict. If strict is enabled, function type parameters are contravariant checked. In simple terms, If A extends B is true, you should be able to use an A as a B. If you can't, then A extends B is not true. Therefore, even if a string is assignable to unknown, you cannot assign an unknown to a string, hence the error. In any, you can assign a string to any and vice versa. hence the solution. – dom.macs Sep 27 '21 at 02:07