Angular 19 to Angular 20 Upgrade
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 f
SKILL.mdskills/angular/upgrades/hops/angular-19-to-20/SKILL.md
GitHubAngular 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.mdskills/angular/upgrades/di/angular-v20-injector-injectflags-cleanup/SKILL.mdskills/angular/upgrades/router/angular-v20-guards-redirects-route-validation/SKILL.mdskills/angular/upgrades/resources/angular-v20-resource-rxresource-migration/SKILL.mdskills/angular/upgrades/zoneless/angular-v20-zoneless-api-rename/SKILL.mdskills/angular/upgrades/templates/angular-v20-template-operator-compat/SKILL.mdskills/angular/upgrades/build/angular-v20-module-resolution-bundler/SKILL.mdskills/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.jsontsconfig.jsontsconfig.app.jsontsconfig.spec.json- base tsconfigs
moduleResolution- custom builders
- custom test builders
- Angular Material usage
afterRenderafterEveryRenderTestBed.flushEffectsTestBed.tickprovideExperimentalCheckNoChangesForDebugprovideCheckNoChangesConfigprovideExperimentalZonelessChangeDetectionprovideZonelessChangeDetectionng-reflect-*provideNgReflectAttributesRedirectFn- route guards and resolvers
- guard arrays
- string guards
RedirectCommandRoute.redirectTocanMatch- commands array types
resourcerxResourceResourceStatus- 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.getInjectFlagsInjector.getEnvironmentInjector.getTestBed.injectAsyncPipeusage in testsPendingTasks.runPendingTasks.addDatePipe- week-year formatter
Y redirectTo+canMatchroute 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:
ng update @angular/core@20 @angular/cli@20
If local CLI is unreliable, use:
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.
ng update @angular/material@20
or:
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, orng-reflect-*dependencies. - Do not rely on
ModuleResolutioninheritance 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.
-
moduleResolutionis aligned tobundler. - 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 buildnpm run testnpm run lintnpm run e2eng build --configuration productionnpm run build:ssrnpm run prerendernpm 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 incorrectlyafterRenderremainsTestBed.flushEffects()remains- deprecated zoneless/check-no-changes providers remain
- production/test code depends on
ng-reflect-* - direct
RedirectFncalls assume sync return - Resource/RxResource old API remains
ResourceStatusenum usage remains- template
inorvoidconflicts 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()remainsInjectFlagsremains- untyped/string-token
Injector.get()remains in critical code - AsyncPipe error reporting breaks tests without resolution
PendingTasks.runreturn value is still relied upon- suspicious DatePipe
Yusage remains in critical flows - parenthesized optional/nullish template expressions can throw
- routes combine
redirectToandcanMatch - Material/style regressions are unreviewed
- SSR/resource behavior is unvalidated in SSR/resource apps
- workspace config is unstable
Expected Output
- Upgrade summary.
- Changelog baseline summary.
- Testing, router, DI, and resource migration summary.
- Validation result.
- 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.
moduleResolutionis aligned tobundler.- 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.