Hey devs! đź‘‹
Welcome back to the RxJS Subject series. In this post, we’ll explore a unique use case — the Void Subject (Subject<void>
). This type of Subject doesn't carry any value. It simply signals that something happened, without caring about what that "something" is.
đź§ľ What is a Void Subject?
By declaring a Subject<void>
, you're signaling that no data is being passed—only the event itself matters.
Syntax:
const subject = new Subject<void>();
đź’ˇ Practical Example in Angular
Here’s a real-world Angular example demonstrating how to use a Subject<void>
.
HTML
<h3>Void Subject</h3>
<div class="text-wrapper">
<div class="text">
<button class="btn-ghost" (click)="sendVoidSubject()" type="button">
Send
</button>
</div>
<div class="example">
<p>Void Subject Value:</p>
@for (item of voidObservable | async; track $index) {
<div class="card">
<div class="index">{{$index}}</div>
<div class="data">{{ 'void subject emitted: ' + item | json }}</div>
</div>
}
</div>
</div>
TypeScript
import { Component, OnInit } from '@angular/core';
import { CommonModule } from '@angular/common';
import { Subject, scan } from 'rxjs';
import { FormsModule } from '@angular/forms';
@Component({
selector: 'app-rxjs-operator',
standalone: true,
imports: [CommonModule, FormsModule],
templateUrl: './rxjs-operator.html',
styleUrl: './rxjs-operator.scss',
})
export class RxjsOperator implements OnInit {
voidSubject = new Subject<void>();
voidObservable = this.voidSubject.asObservable().pipe(
scan((acc: string[], curr: any) => [...acc, curr], [])
);
sendVoidSubject() {
this.voidSubject.next();
}
ngOnInit() {}
}
When the button is clicked, a new "void" event is triggered. We're using the async
pipe to subscribe and display those events.
🔍 Use Cases
âś… Case 1: Emitting Events Without Data
Clicking the button emits an event, but there's no value passed—just undefined
.
âś… Case 2: Multiple Subscribers
Just like a regular Subject
, a Subject<void>
can have multiple subscribers. When an event is triggered, all subscribers are notified.
⚠️ Case 3: Trying to Emit a Value
What if you mistakenly try to pass a value?
this.voidSubject.next('Oops !');
You’ll get a compile-time error:
Argument of type 'string' is not assignable to parameter of type 'void'.
This prevents accidental misuse.
📝 Important Note
You might think declaring a generic Subject()
without a type is the same:
const subject = new Subject();
But this is actually a Subject<void>
. It won't prevent you from passing values, even when you shouldn't. That’s why it’s safer and more intentional to define your Subject explicitly as Subject<void>
.
âś… Summary
-
Subject<void>
is useful when the value doesn’t matter—only the fact that something occurred. - It helps avoid unintentional data emission.
- It supports multiple subscribers just like a normal Subject.
- It improves code clarity and TypeScript safety.
💬 Got questions or use cases you want to share? Drop a comment below! Let's discuss more Javascript magic. ✨
✍️ Author: Vetriselvan
👨‍💻 Frontend Developer | 💡 Code Enthusiast | 📚 Lifelong Learner | ✍️ Tech Blogger | 🌍 Freelance Developer
Top comments (3)
Ok, it's curious that you can create and use a
Subject<void>
, but in practice, given that Subject and BehaviorSubject carry events and state, it doesn't make sense to emit an empty event.An event should always carry some metainformation, like "what" just happened?
Exactly! I haven't used this in my application either. But it might be useful in cases involving the destroy subject, especially when we need it just for unsubscribe purposes.
`ts
private _destroy$ = new Subject();
takeUntil(_destroy$);
this._destroy$.next();
this._destroy$.complete()`
Here's a "destroy" Subject you can use to remove an HTML element:
stackblitz.com/edit/self-destroyin...
Actually, the source type could also be
Subject<any>
, orSubject<unknown>
,Subject<Event>
đź‘€