Все вычисляемые или просто асинхронные вещи нужно хранить в Observable. Будет полный аналог вашего computed.
Например есть переменная
src = new BehaviorSubject(1);
От нее вычисляем класс
myClass = this.src.pipe(map(v => v === 1 ? 'one' : 'two'))
В шаблоне будет
div [ngClass]="myClass | async"
При изменении src, т.е.
src.next(2)
Будет пересчитан myClass (один раз) и изменится шаблон (тоже один раз, если нет других причин для изменений и стоит on-push)
А если его нигде не запросить, то пересчета не будет, т.к. это ленивое вычисление, так же как и computed.
Подобным образом менеджатся любые данные и события, и это гораздо более гибкая система, чем скрытые геттеры-сеттеры в vue, хотя иногда более многословная. И требует больше времени на освоение.