What happened?
In modern Angular (v14+), services are typically obtained via a class field initialiser:
private readonly inner = inject(InnerService);
Fallow does not recognise this as a typed binding, so any this.inner.member chain fails to credit member as used on InnerService. Every member of an inject()-acquired service that is only consumed via the field chain is reported as an unused class member.
The legacy constructor-parameter form (constructor(private readonly inner: InnerService) {}) does not have this problem.
Reproduction
mkdir -p /tmp/fallow-repro/src && cd /tmp/fallow-repro
// src/inner.service.ts
import { Injectable } from '@angular/core';
@Injectable({ providedIn: 'root' })
export class InnerService {
readonly aaa = 1; // used via this.inner.aaa → expected NOT reported
readonly bbb = 2; // used via this.inner.bbb → expected NOT reported
readonly ccc = 3; // genuinely unused → expected reported
}
// src/outer.service.ts
import { computed, inject, Injectable } from '@angular/core';
import { InnerService } from './inner.service';
@Injectable({ providedIn: 'root' })
export class OuterService {
private readonly inner = inject(InnerService);
readonly forwardedAaa = this.inner.aaa;
readonly doubledBbb = computed(() => this.inner.bbb * 2);
}
// src/main.ts
import { OuterService } from './outer.service';
void OuterService;
fallow dead-code --format json 2>/dev/null \
| jq '.unused_class_members[] | {parent_name, member_name, line}'
Expected behavior
Only InnerService.ccc is flagged. aaa and bbb are reachable via the inject()-bound inner field on OuterService.
(OuterService.forwardedAaa and OuterService.doubledBbb are also flagged, but that is unrelated and expected — void OuterService only references the class identity, not its instance members.)
Actual
aaa, bbb, AND ccc are all reported as unused on InnerService:
Switching OuterService to the legacy form clears the false positives — only ccc is then reported:
constructor(private readonly inner: InnerService) {}
Fallow version
2.56.0
Operating system
macOS
Configuration
What happened?
In modern Angular (v14+), services are typically obtained via a class field initialiser:
Fallow does not recognise this as a typed binding, so any
this.inner.memberchain fails to creditmemberas used onInnerService. Every member of aninject()-acquired service that is only consumed via the field chain is reported as an unused class member.The legacy constructor-parameter form (
constructor(private readonly inner: InnerService) {}) does not have this problem.Reproduction
Expected behavior
Only
InnerService.cccis flagged.aaaandbbbare reachable via theinject()-boundinnerfield onOuterService.{ "parent_name": "InnerService", "member_name": "ccc", "line": 7 }(
OuterService.forwardedAaaandOuterService.doubledBbbare also flagged, but that is unrelated and expected —void OuterServiceonly references the class identity, not its instance members.)Actual
aaa,bbb, ANDcccare all reported as unused onInnerService:{ "parent_name": "InnerService", "member_name": "aaa", "line": 5 } { "parent_name": "InnerService", "member_name": "bbb", "line": 6 } { "parent_name": "InnerService", "member_name": "ccc", "line": 7 }Switching
OuterServiceto the legacy form clears the false positives — onlycccis then reported:Fallow version
2.56.0
Operating system
macOS
Configuration
default