Analog
On this page

Type-safe Routing

Typed routing is an opt-in experimental feature that adds checked route paths and parameters to Analog's file router. It is disabled by default. Its APIs and generated types may change while the feature is experimental.

Enable it explicitly with experimental.typedRouting in your existing Vite configuration:

import analog from '@analogjs/platform';
import { defineConfig } from 'vite';

export default defineConfig({
  plugins: [analog({ experimental: { typedRouting: true } })],
});

Analog generates src/routeTree.gen.d.ts. Include it in each tsconfig that checks your application, including separate browser, server, and test configurations. Add it to your existing files list, or ensure an include pattern covers it:

{
  "include": ["src/**/*.d.ts"]
}

Preserve your other files and include entries. Paths are relative to the tsconfig declaring them. Inherited lists apply unless a child tsconfig overrides them.

Analog checks inclusion in the tsconfig selected by its Angular compiler plugin and reports an error with the path to add when it is missing. Application entry files are not modified, and components do not need to import the declaration.

Keep the generated file in source control. Start the dev server to generate it before running standalone type checks. Page additions, renames, and removals regenerate the declaration during development. Production builds reject stale checked-in route tables; the first build can generate a missing table.

To customize the output or allow regeneration during builds:

analog({
  experimental: {
    typedRouting: {
      outFile: 'src/routeTree.gen.d.ts',
      verifyOnBuild: false,
    },
  },
});

Custom output paths must end in .d.ts and be included in the relevant tsconfigs.

Import LinkTo from @analogjs/router into your component's imports and bind a destination to [linkTo]:

<a linkTo="/shipping">Shipping</a>
<a
  [linkTo]="{
    path: '/products/[id]',
    params: { id: product.id },
    query: { tab: 'details' },
    hash: 'reviews'
  }"
  routerLinkActive="active"
>
  Details
</a>

The generated route table checks the path, required named parameters, and their value types together. Static routes accept string shorthand, such as linkTo="/shipping" or [linkTo]="'/shipping'". Only generated routes with no parameters allow this shorthand; dynamic and catch-all routes require a destination object. Unknown paths, unrestricted string values, positional command arrays, and UrlTree values are rejected with strictTemplates enabled. Use the destination object with query and hash to add query parameters and fragments, including for static routes. Binding null or undefined disables the link.

LinkTo composes Angular's RouterLink, preserving href generation, navigation, modifier clicks, and target behavior. It exposes target, queryParamsHandling, preserveFragment, skipLocationChange, replaceUrl, and state. Import Angular's RouterLinkActive separately to use active classes on the link or an ancestor. Use [linkTo] on its own; do not also apply [routerLink] to the same element.

Dynamic parameters accept strings or numbers. Numbers are converted to strings when building links and navigating. Required catch-all parameters accept non-empty arrays of string or number segments; optional catch-all parameters may be omitted or empty. For required catch-all arrays stored in variables, use the tuple type [string | number, ...(string | number)[]] to preserve the non-empty guarantee. Query values are strings or string arrays, and hash supplies the fragment. URL path segments are encoded automatically.

Use injectNavigate inside an Angular injection context:

import { injectNavigate } from '@analogjs/router';

const navigate = injectNavigate();
navigate('/products/[id]', { params: { id: 42 } }, { replaceUrl: true });

Use toRoute when you need link data in TypeScript. It does not require an injection context:

import { toRoute } from '@analogjs/router';

const link = toRoute('/products/[id]', { params: { id: 42 } });
// link.path is ['/', 'products', '42']

The result contains Angular router commands in path, plus queryParams and fragment. These properties can be passed to Angular's router APIs. For template links, use [linkTo] as shown above.

Read parameters as signals

import { injectParams, injectQuery } from '@analogjs/router';

const params = injectParams('/products/[id]');
const query = injectQuery('/products/[id]');
// params().id is a string; query()['page'] is a raw query value.

Use these helpers in a component rendered by the specified route. The path narrows TypeScript types; it does not select another active route. Parameters include ancestor parameters, and catch-all values are normalized to arrays. The helpers accept { injector } when called outside an injection context.

Values remain raw Angular router values. Exporting a schema does not validate or coerce these signals. For example, "42" stays a string.

Type checking comes from the generated table. The experimental.typedRouting option enables generation for the feature as a whole; no additional router provider or per-helper experimental flag is required.

Compatibility

Existing file routing, Markdown routes, Nitro configuration, and Angular compiler options remain unchanged. Additional page and content directories participate in generation. Without the generated declaration in the TypeScript program, typed helper calls fail to compile. Use Angular's existing router APIs for navigation without generated route types.

Type checking

Use Angular's compiler with your application tsconfig to check TypeScript and templates:

pnpm exec ngc -p tsconfig.app.json --noEmit

Template checking requires angularCompilerOptions.strictTemplates: true. If you use fastCompile or disable type checking in Vite, run this check separately; enabling typed routing does not override those compiler settings.