fix(@schematics/angular): set explicit type for the app-shell component #34450

Open
meakib opened 8:11pm on October 20, 2026 wants to merge 0 Ξ” into angular/angular-cli main from
fix/app-shell-component-type

Pull Request Overview

  • Opened on October 20, 2026
  • Status Open
  • Commit count 2 with first commit October 20, 2026

Total Delta

0 Total Diff Delta

Open Days

Open 19 weekdays

Test Delta

0 Diff Delta in Test Files
Breakdown by Phase

How long has this pull request spent in each phase of its lifecycle?

Fraction of total time Business days Phase
N/A 0.0 days Issue creation to work beginning
 
0.0 days Authoring 1 commit before pull request opened for review
 
0.0 days Awaiting first review
 
18.4 days Revising work with 1 commit in response to 2 reviews that left 2 comments

Total time for pull request still awaiting merge (longer than repo's target): 18.4 business days

Author avatar

fix(@schematics/angular): set explicit type for the app-shell component

ng generate app-shell adds an AppShell import from ./app-shell/app-shell, but the component it generates inherits the workspace type option. In workspaces that set "@schematics/angular:component": { "type": "component" }, such as those updated to v20, the component was generated as app-shell.component.ts and the import failed to resolve.

Pass an empty type, as the library schematic does (661609e3e).

Refs #34449

Command

generate

Is this a regression?

  • [x] Yes, this behavior used to work in the previous version

The previous version in which this bug was not present was

19.x (before the v20 file naming change)

Description

ng generate app-shell and ng generate module <name> --route <path> --module <parent> generate a component and then reference it with a hard-coded file path and class name. Both assume the v20+ defaults (no type in the file or class name). When the workspace configures a component type, the component inherits it and the hard-coded references no longer match, so the build fails.

Workspaces get a component type in two common ways:

  1. Every workspace updated to v20 with ng update: the migration that keeps the previous style guide behaviour (fdc6291dda) adds "@schematics/angular:component": { "type": "component" }.
  2. ng new --file-name-style-guide=2016, which adds { "type": "component", "addTypeToClassName": false }.

Hard-coded references:

  • packages/schematics/angular/app-shell/index.ts: withAppShell(AppShell) and insertImport(..., 'AppShell', './app-shell/app-shell').
  • packages/schematics/angular/module/files/.../__name@dasherize__-routing__typeSeparator__module.ts.template (and the non-routing module template for --route without a routing module): import { <%= classify(name) %> } from './<%= dasherize(name) %>';

The library schematic had the same problem (#26981) and was fixed in 661609e3e by passing an explicit type: '' to the component schematic.

Minimal Reproduction

app-shell (updated-workspace configuration):

ng new ws --defaults
cd ws
# what `ng update` to v20 adds to angular.json under projects.ws.schematics:
#   "@schematics/angular:component": { "type": "component" }
ng generate app-shell
ng build

Generated src/app/app-shell/app-shell.component.ts contains export class AppShellComponent {}, but src/app/app.config.server.ts contains:

import { AppShell } from './app-shell/app-shell';
...
provideServerRendering(withRoutes(serverRoutes), withAppShell(AppShell))

module --route (2016 file name style):

ng new ws --no-standalone --file-name-style-guide=2016 --defaults
cd ws
ng generate module feature --route feature --module app
ng build

Generated src/app/feature/feature-routing.module.ts:

import { Feature } from './feature'; // the file is feature.component.ts

Exception or Error

# app-shell
✘ [ERROR] TS2307: Cannot find module './app-shell/app-shell' or its corresponding type declarations. [plugin angular-compiler]
✘ [ERROR] Could not resolve "./app-shell/app-shell"

# module --route
✘ [ERROR] Could not resolve "./feature"
✘ [ERROR] TS2307: Cannot find module './feature' or its corresponding type declarations. [plugin angular-compiler]

Your Environment

Angular CLI       : 22.2.3
Node.js           : 24.15.0
Package Manager   : npm 11.12.1
Operating System  : darwin arm64
@schematics/angular : 22.2.3

Anything else relevant?

  • Affected since 20.0.0 (hard-coded names from 23fc8e1e17, "generate components without a .component extension/type"). Same code on 21.2.x and 22.2.x.
  • Suggested fix: follow 661609e3e and pass type: '' (and addTypeToClassName: false, so the class name stays AppShell/Feature) to the component schematic in app-shell and module, so the generated files always match the references. Happy to send a PR.
  • The module --route case with addTypeToClassName: false also hits #<issue for 01> (wrong NgModule declaration); link the two once filed.

Comments Threads Pending Resolution

alan-agius4 reviewed on October 21, 2026
alan-agius4 left a comment

Thanks for the contribution! Left a comment regarding the test in `packages/schematics/angular/app-shell/index_spec.ts`.

gemini-code-assist[bot] reviewed on October 20, 2026
gemini-code-assist[bot] left a comment

## Code Review

This pull request updates the Angular `app-shell` schematic to explicitly set the component `type` option to an empty string (`type: ''`). This prevents the generated app-shell component from inheriting a custom component type from the workspace defaults, which would otherwise alter the file and class names and break the expected `AppShell` import. Additionally, a unit test has been added to verify this behavior by emulating workspace defaults. There are no review comments to address, and the changes look solid.

Resolved Comment Threads

alan-agius4 reviewed on October 21, 2026
alan-agius4 left a comment

Thanks for the contribution! Left a comment regarding the test in `packages/schematics/angular/app-shell/index_spec.ts`.

packages/schematics/angular/app-shell/index_spec.ts
Outdated
156
      expect(tree.exists('/projects/bar/src/app/app-shell/app-shell.ts')).toBe(true);
157
      expect(tree.exists('/projects/bar/src/app/app-shell/app-shell.component.ts')).toBe(false);
158
      const content = tree.readContent('/projects/bar/src/app/app.config.server.ts');
159
      expect(content).toContain(`import { AppShell } from './app-shell/app-shell';`);
160
    });