question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Subject.prototype.next() should only accept T, not T | undefined

See original GitHub issue

RxJS version: 5.4.3

Code to reproduce:

const subject = new Subject<string>()

subject.next()

Expected behavior:

Compile error

Actual behavior:

Compiles

Additional information:

next()'s argument is typed as optional, which means it allows undefined even if the Subject’s type does not. It should only allow T, not T | undefined.

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Reactions:8
  • Comments:23 (16 by maintainers)

github_iconTop GitHub Comments

5reactions
Dynaloncommented, Aug 21, 2018

The current situation in v6.x is still very unexpected to me as a TypeScript developer when using the --strict tsc compiler option (or the --strictNullChecks option to be specific):

const someSubject = new Subject<string[]>();

// will throw an error when s is undefined!
// Worse: The type of arr is inferred as string[], but it
// actually should have been (string[] | undefined)
someSubject.subscribe(arr => arr.forEach(s => console.info(s));

// this line should be a compile error in --strict mode
someSubject.next();

rxjs Subjects will use the generic type argument and make it nullable: string[] | undefined in this case which is somewhat counterintuitive. If I wanted to allow undefined, I would have defined the type as Subject<string[] | undefined>. These explicit defines are common and wanted if I turn on strictNullChecks.

The fact that I always have to pass undefined when I create a Subject<void> is not surprising, but standard when using TypeScript in strict mode and should be known to the developer:

function print<T>(t: T) {
    console.info(t);
}
// this is a compiler error
print<void>();
// this is ok
print<void>(undefined);

I don’t think rxjs should do some “magic” conversion of T to T | undefined as me as a developer would not expect this. I ran into a bug where I had a .next() in the code, and the subscriber function had a default argument initializer - so it worked at first. In a refactor I removed the default argument in the subscriber function and the tsc compiler did not report an error, but turned into a runtime error. The whole idea of strictNullChecks is to avoid this.

Even worse is that the typing of the subscribe() function is wrong: It is infered as T (and displayed as T in the IntelliSense) but should actually be T | undefined - the tsc compiler will then enforce the non-null/non-undefined checks inside the subscriber function and we are back to type safety:

const someSubject = new Subject<string[]>();

someSubject.subscribe(arr => {
    // assuming arr will be inferred to (string[] | undefined) then
    // tsc will error here, saying that arr is possibly 'undefined'
    arr.forEach(s => console.info(s)
});

Please reconsider changing this. This change affects only users which enable strict nullchecks, that option is off by default and when off still allows me to call .next() without passing undefined.

4reactions
cartantcommented, Mar 14, 2021
Read more comments on GitHub >

github_iconTop Results From Across the Web

Generator.prototype.next() - JavaScript - MDN Web Docs
Generator.prototype.next(). The next() method returns an object with two properties done and value . You can also provide a parameter to the next...
Read more >
How to Avoid the Infamous "Cannot read properties of ... - Bitovi
That error message is telling you the function is returning undefined implicitly, but its return type does not include undefined in it. Awesome!...
Read more >
How does JavaScript .prototype work? - Stack Overflow
In JavaScript you first create an object (there is no concept of class), ... While as said I can't call setAmountDue(), getAmountDue() on...
Read more >
Class inheritance - The Modern JavaScript Tutorial
The task may seem simple, but it isn't. The engine knows the current object this , so it could get the parent method...
Read more >
Google TypeScript Style Guide
Type parameters, like in Array<T> , may use a single upper case character ( T ) or UpperCamelCase ... The bean that will...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found