Upgrade an Angular application from Angular 19.x to Angular 20.x using a controlled major-hop process. Use when the project is ready to move from Angular 19 to Angular 20 and needs explicit handling for TypeScript 5.8+, moduleResolution bundler, testing behavior, DI deprecations, router redirects, Resource API changes, template operator conflicts, ng-reflect cleanup, and SSR/module-resolution risk.
Installs into .claude/skills of the current project.
Are you the author of Angular Upgrade Hops Angular 19 To 20?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/janpereira-dev-angular-upgrade-hops-angular-19-to-20)
---
id: angular.upgrade.hops.angular-19-to-20
name: Angular 19 to Angular 20 Upgrade
description: >
Upgrade an Angular application from Angular 19.x to Angular 20.x using a controlled major-hop process. Use when the project is ready to move from Angular 19 to Angular 20 and needs explicit handling for TypeScript 5.8+, moduleResolution bundler, testing behavior, DI deprecations, router redirects, Resource API changes, template operator conflicts, ng-reflect cleanup, and SSR/module-resolution risk.
stack:
- Angular
- TypeScript
category: upgrade
status: stable
version: 0.10.0
owner: NgAutoPilot
triggers:
- Angular 19 to 20
- Angular 20 upgrade
- moduleResolution bundler
- Resource API migration
compatibility:
angular:
min: "19"
---
# Angular 19 to Angular 20 Upgrade
## Purpose
Upgrade an Angular application from Angular 19.x to Angular 20.x using a controlled major-hop process.
## When to Use
- The project uses Angular 19.x.
- The target next hop is Angular 20.x.
- The Angular 18 -> 19 validation gate passed.
- Angular Material usage is known.
- TypeScript configuration is known.
- Node.js runtime is known.
- Router guard/redirect usage is known.
- Resource/RxResource usage is known.
- Test strategy is known.
## When Not to Use
- The project is AngularJS 1.x.
- The project is Angular 18.x or lower.
- The project is already Angular 20 or later.
- The previous Angular 18 -> 19 validation gate failed.
- Angular Material v19 migration has unresolved critical blockers.
- The project has unknown TypeScript configuration.
- The project uses unsupported Node.js.
- The task is only zoneless migration.
- The task is only Resource API refactor.
- The task is only testing cleanup.
## Mandatory Cross-Skill Routing
Before upgrading from Angular 19 to Angular 20, run:
`skills/angular/upgrades/changelog/angular-major-changelog-risk-review/SKILL.md`
If the changelog review returns `FAIL_BLOCK_NEXT_HOP`, do not continue to Angular 20.
## Recommended Cross-Skill Routing
- `skills/angular/upgrades/testing/angular-v20-testing-errors-effects-animations/SKILL.md`
- `skills/angular/upgrades/di/angular-v20-injector-injectflags-cleanup/SKILL.md`
- `skills/angular/upgrades/router/angular-v20-guards-redirects-route-validation/SKILL.md`
- `skills/angular/upgrades/resources/angular-v20-resource-rxresource-migration/SKILL.md`
- `skills/angular/upgrades/zoneless/angular-v20-zoneless-api-rename/SKILL.md`
- `skills/angular/upgrades/templates/angular-v20-template-operator-compat/SKILL.md`
- `skills/angular/upgrades/build/angular-v20-module-resolution-bundler/SKILL.md`
- `skills/angular/upgrades/debug/angular-v20-ng-reflect-cleanup/SKILL.md`
## Required Inputs
- `package.json`
- lock file
- Angular package versions
- Angular CLI version
- Angular Material version
- Angular CDK version
- TypeScript version
- RxJS version
- Zone.js version
- Node.js version
- `angular.json`
- `tsconfig.json`
- `tsconfig.app.json`
- `tsconfig.spec.json`
- base tsconfigs
- `moduleResolution`
- custom builders
- custom test builders
- Angular Material usage
- `afterRender`
- `afterEveryRender`
- `TestBed.flushEffects`
- `TestBed.tick`
- `provideExperimentalCheckNoChangesForDebug`
- `provideCheckNoChangesConfig`
- `provideExperimentalZonelessChangeDetection`
- `provideZonelessChangeDetection`
- `ng-reflect-*`
- `provideNgReflectAttributes`
- `RedirectFn`
- route guards and resolvers
- guard arrays
- string guards
- `RedirectCommand`
- `Route.redirectTo`
- `canMatch`
- commands array types
- `resource`
- `rxResource`
- `ResourceStatus`
- template properties named `in`
- template references named `in`
- template properties named `void`
- template references named `void`
- templates with parenthesized optional chaining
- animation tests
- event listener error tests
- `TestBed.get`
- `InjectFlags`
- `Injector.get`
- `EnvironmentInjector.get`
- `TestBed.inject`
- `AsyncPipe` usage in tests
- `PendingTasks.run`
- `PendingTasks.add`
- `DatePipe`
- week-year formatter `Y`
- `redirectTo` + `canMatch` route configs
- current build/test/lint/e2e scripts
- production build scripts
- SSR/prerender scripts
- screenshot/golden tests
## Dependency Upgrade
### Node.js
Use the Angular version compatibility matrix as the source of truth.
### TypeScript
Angular 20 requires TypeScript 5.8 or later.
### Angular Core and CLI
Run:
```bash
ng update @angular/core@20 @angular/cli@20
```
If local CLI is unreliable, use:
```bash
npx @angular/cli@20 update @angular/core@20 @angular/cli@20
```
### Angular Material
If the project uses Angular Material, update to v20 after Angular core and CLI succeed.
```bash
ng update @angular/material@20
```
or:
```bash
npx @angular/cli@20 update @angular/material@20
```
## Required Code Changes
### 1. `moduleResolution: "bundler"`
Validate and align tsconfig inheritance to use `moduleResolution: "bundler"`.
### 2. Replace `afterRender` with `afterEveryRender`
Update render callbacks to the new API.
### 3. Replace `TestBed.flushEffects()` with `TestBed.tick()`
Update tests using effect flushing helpers.
### 4. Rename check-no-changes provider
Replace `provideExperimentalCheckNoChangesForDebug` with `provideCheckNoChangesConfig`.
### 5. Remove `ng-reflect-*` dependency
Avoid tests or production logic depending on Angular debug attributes.
### 6. Handle async `RedirectFn` return values
Update direct calls to `RedirectFn` to handle Observable or Promise results.
### 7. Resource API `request` to `params`
Update `resource` usage to the `params` option.
### 8. RxResource `request` / `loader` to `params` / `stream`
Update `rxResource` usage to the new API.
### 9. Replace `ResourceStatus` enum usage
Remove enum-style `ResourceStatus` usage.
### 10. Rename zoneless provider
Replace `provideExperimentalZonelessChangeDetection` with `provideZonelessChangeDetection`.
### 11. Template `in` and `void` conflicts
Rename colliding template properties or references.
### 12. Router commands arrays are readonly
Stop mutating router commands arrays.
### 13. Animation test timing
Review animation-related test timing changes.
### 14. Event listener errors rethrown in tests
Review tests that expect swallowed listener errors.
### 15. Guard arrays no longer accept `any`
Remove `any` from route guard arrays.
### 16. Replace `TestBed.get()` with `TestBed.inject()`
Update all touched tests.
### 17. Remove `InjectFlags`
Replace `InjectFlags` with typed options or explicit handling.
### 18. Use specific `ProviderToken<T>` in `Injector.get`
Avoid untyped or string-token injector usage in critical code.
### 19. AsyncPipe error reporting
Adjust tests and error handling to the new behavior.
### 20. PendingTasks.run return behavior
Stop relying on the return value of `PendingTasks.run`.
### 21. DatePipe week-year formatter
Review suspicious `Y` format usage.
### 22. Template parentheses behavior
Review parenthesized optional chaining and nullish expressions.
### 23. `redirectTo` with `canMatch`
Resolve route configs that combine `redirectTo` and `canMatch`.
## Do
- Run the Angular 19 changelog review before changing package versions.
- Keep module resolution, tests, router, DI, and resource behavior explicit.
- Validate production and SSR builds when they are used.
- Route risky test, build, and router behavior to the dedicated skills.
- Keep Material/MDC validation explicit if Material is used.
## Do Not
- Do not continue if Angular 19 changelog review failed.
- Do not keep `TestBed.get`, `InjectFlags`, or `ng-reflect-*` dependencies.
- Do not rely on `ModuleResolution` inheritance accidentally.
- Do not mix zoneless modernization, control flow, defer, or standalone adoption into the hop.
## Review Checklist
- [ ] Angular 19 changelog review passed.
- [ ] TypeScript 5.8+ is compatible.
- [ ] `moduleResolution` is aligned to `bundler`.
- [ ] Testing helpers are updated.
- [ ] DI deprecations are removed.
- [ ] Router redirects and guards are reviewed.
- [ ] Resource API usage is migrated.
- [ ] Template operator conflicts are resolved.
- [ ] `ng-reflect-*` dependence is removed.
- [ ] Material/MDC regression risk is reviewed.
- [ ] Production build passes.
## Validation
Run only existing scripts:
- `npm run build`
- `npm run test`
- `npm run lint`
- `npm run e2e`
- `ng build --configuration production`
- `npm run build:ssr`
- `npm run prerender`
- `npm run serve:ssr`
## Validation Gate
Use `FAIL_BLOCK_NEXT_HOP` when:
- Angular 19 changelog risk review failed
- TypeScript version is unsupported
- build fails
- tests fail
- production build fails
- Angular CLI update is incomplete
- Angular Material update is incomplete in a Material project
- `moduleResolution: "bundler"` is missing or overridden incorrectly
- `afterRender` remains
- `TestBed.flushEffects()` remains
- deprecated zoneless/check-no-changes providers remain
- production/test code depends on `ng-reflect-*`
- direct `RedirectFn` calls assume sync return
- Resource/RxResource old API remains
- `ResourceStatus` enum usage remains
- template `in` or `void` conflicts remain
- router commands are mutated despite readonly typing
- animation DOM tests are unresolved
- event listener errors are suppressed globally instead of fixed
- route guard arrays use `any`
- string guards remain without migration plan
- `TestBed.get()` remains
- `InjectFlags` remains
- untyped/string-token `Injector.get()` remains in critical code
- AsyncPipe error reporting breaks tests without resolution
- `PendingTasks.run` return value is still relied upon
- suspicious DatePipe `Y` usage remains in critical flows
- parenthesized optional/nullish template expressions can throw
- routes combine `redirectTo` and `canMatch`
- Material/style regressions are unreviewed
- SSR/resource behavior is unvalidated in SSR/resource apps
- workspace config is unstable
## Expected Output
1. Upgrade summary.
2. Changelog baseline summary.
3. Testing, router, DI, and resource migration summary.
4. Validation result.
5. Gate decision.
## Exit Criteria
- Angular 19 changelog review has passed.
- Angular dependencies are upgraded to Angular 20-compatible versions.
- Angular CLI is upgraded to v20.
- Angular Material/CDK are upgraded to v20 only if used.
- TypeScript 5.8+ compatibility is confirmed.
- `moduleResolution` is aligned to `bundler`.
- Testing behavior is reviewed.
- DI deprecations are removed.
- Router redirect behavior is reviewed.
- Resource API migration is reviewed.
- `ng-reflect-*` dependency is removed.
- Angular Material and style regressions are reviewed.
- Validation gate result is explicit.
- The next hop is not started automatically.