Which @angular/* package(s) are the source of the bug?
compiler-cli, language-service
Is this a regression?
No
Description
Since #70188 (22.2.0), a template can read private members of its component. TypeScript doesn't see those reads though, so a private member that is only used in the template is still reported as unused (TS6133).
import {Component, signal} from '@angular/core';
@Component({
selector: 'app-root',
template: `
<p>{{ privateTitle() }}</p>
<p>{{ protectedTitle() }}</p>
`,
})
export class App {
private readonly privateTitle = signal('private member');
protected readonly protectedTitle = signal('protected member');
}
With "noUnusedLocals": true in tsconfig.json, ng build fails:
✘ [ERROR] TS6133: 'privateTitle' is declared but its value is never read. [plugin angular-compiler]
src/app.ts:12:19:
12 │ private readonly privateTitle = signal('private member');
╵ ~~~~~~~~~~~~
ng serve fails the same way on startup.
Without noUnusedLocals the build passes, but the editor still greys out privateTitle and offers the "Remove unused declaration for: 'privateTitle'" quick fix, which breaks the template when applied. The Angular language service forwards TypeScript's suggestion diagnostics as is, so having the extension installed doesn't change this.
protectedTitle isn't reported in either case, since TypeScript doesn't track unused protected members.
I'd expect a private member read by the component's own template to count as used, both in the build and in the editor. Whatever the fix, private members that are genuinely unused should still be reported, since that's what noUnusedLocals is for.
This came up in #70514 (comment), opening a separate issue so it can be tracked on its own.
Please provide a link to a minimal reproduction of the bug
The component above, with "noUnusedLocals": true in tsconfig.json.
Please provide the exception or error you saw
TS6133: 'privateTitle' is declared but its value is never read.
Please provide the environment you discovered this bug in (run ng version)
Angular CLI : 22.2.0
Angular : 22.2.0
Node.js : 24.21.0
Package Manager : npm 11.19.0
Operating System : darwin arm64
┌───────────────────────────┬───────────────────┬───────────────────┐
│ Package │ Installed Version │ Requested Version │
├───────────────────────────┼───────────────────┼───────────────────┤
│ @angular/build │ 22.2.0 │ 22.2.0 │
│ @angular/cli │ 22.2.0 │ 22.2.0 │
│ @angular/common │ 22.2.0 │ 22.2.0 │
│ @angular/compiler │ 22.2.0 │ 22.2.0 │
│ @angular/compiler-cli │ 22.2.0 │ 22.2.0 │
│ @angular/core │ 22.2.0 │ 22.2.0 │
│ @angular/platform-browser │ 22.2.0 │ 22.2.0 │
│ rxjs │ 7.8.2 │ ~7.8.0 │
│ typescript │ 6.0.3 │ ~6.0.2 │
└───────────────────────────┴───────────────────┴───────────────────┘
Anything else?
No response
Which @angular/* package(s) are the source of the bug?
compiler-cli, language-service
Is this a regression?
No
Description
Since #70188 (22.2.0), a template can read
privatemembers of its component. TypeScript doesn't see those reads though, so aprivatemember that is only used in the template is still reported as unused (TS6133).With
"noUnusedLocals": trueintsconfig.json,ng buildfails:ng servefails the same way on startup.Without
noUnusedLocalsthe build passes, but the editor still greys outprivateTitleand offers the "Remove unused declaration for: 'privateTitle'" quick fix, which breaks the template when applied. The Angular language service forwards TypeScript's suggestion diagnostics as is, so having the extension installed doesn't change this.protectedTitleisn't reported in either case, since TypeScript doesn't track unusedprotectedmembers.I'd expect a
privatemember read by the component's own template to count as used, both in the build and in the editor. Whatever the fix, private members that are genuinely unused should still be reported, since that's whatnoUnusedLocalsis for.This came up in #70514 (comment), opening a separate issue so it can be tracked on its own.
Please provide a link to a minimal reproduction of the bug
The component above, with
"noUnusedLocals": trueintsconfig.json.Please provide the exception or error you saw
Please provide the environment you discovered this bug in (run
ng version)Anything else?
No response