Angular Router helper for typed URL parameters.
typed-url is available as an NPM package. You can install typed-url in your Angular project as usual:
$ npm install typed-url --saveIt allows applying type constraints to angular router URL route parameters.
Consider the URL /user/:id/:name. One could wish to only allow integers
numbers in place of :id typed-url makes this posible.
Build-in types
| type | syntax | result type | 
|---|---|---|
| integer | 'int' | number | 
| string | 'string' | string | 
| regex | /^regex$/ | RegExpMatchArray | 
| enum | ['val1', 'val2'] | string | 
| custom validators | new CustomTypeValidator() | depends on you 😁 | 
** app-routing.module.ts **
import { typedUrl } from 'typed-url';
const routes: Routes = [
  { path: '', component: HomeComponent, pathMatch: 'full' },
  { path: 'cars-list', 
    children: [
      // this route only matchs for valid url params
      {
        matcher: typedUrl<CarListRouteParams>(':sort/:sortDir/:color/:constructed/:make', {
          sort: ['name', 'make', 'constructed'],
          sortDir: ['asc', 'desc'],
          color: /^([1-9a-f]{6})$/, // regex produces the result type `RegExpMatchArray`
          constructed: 'int',
          make: 'string'
        }),
        component: CarListComponent
      },
      // catch all invalid and redirect back to default filter.
      { path: '**', redirectTo: 'name/asc/red/2019/audi' }
    ]
  },
  { path: '**', component: PageNotFoundComponent },
];
@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }** CarListComponent **
import { getTypedParams } from 'typed-url';
export interface CarListRouteParams {
  sort: 'name' | 'make' | 'constructed';
  sortDir: 'asc' | 'desc';
  color: RegExpMatchArray;
  constructed: number;
  make: string;
}
@Component({selector: 'car-list'})
export class CarListComponent {
  constructor(
    public route: ActivatedRoute
  ) {
    this.route.paramMap
      .pipe(getTypedParams<CarListRouteParams>())
      .subscribe(_ => {
        // all params have the correct type
        const sort = _.sort;
        const sortDir = _.sortDir;
        const color = _.color[0]; // because it's of type `RegExpMatchArray`
        const constructed = _.constructed;
        const make = _.make;
        import { isNumber } from 'util';
        console.assert( isNumber(constructed) ); // shows -> true
      });
  }
}For the above example one could write a custom TypeValidator
for the CarListRouteParams.color field.
class HexColorValidator extends TypeValidator {
  matches(value: string): boolean {
    return /^([1-9a-f]{6})$/.test(value);
  }
  parse(value: string) {
    return `#${value}`;
  }
}
// and use it like:
const routes = [
  { 
    matcher: typedUrl<ColorRouteParams>(':color', {
      color: new HexColorValidator()
    }),
    component: ColorComponent
  }
];
interface ColorRouteParams {
  color: string;
}