fix(router): Update types for TypeScript nullability support

This commit is contained in:
Miško Hevery 2017-03-24 09:55:52 -07:00 committed by Tobias Bosch
parent c36ec9bf60
commit 56c46d70f7
26 changed files with 230 additions and 223 deletions

View File

@ -25,7 +25,9 @@ import {UrlSegment, UrlSegmentGroup, UrlSerializer, UrlTree} from './url_tree';
import {andObservables, forEach, waitForMap, wrapIntoObservable} from './utils/collection'; import {andObservables, forEach, waitForMap, wrapIntoObservable} from './utils/collection';
class NoMatch { class NoMatch {
constructor(public segmentGroup: UrlSegmentGroup = null) {} public segmentGroup: UrlSegmentGroup|null;
constructor(segmentGroup?: UrlSegmentGroup) { this.segmentGroup = segmentGroup || null; }
} }
class AbsoluteRedirect { class AbsoluteRedirect {
@ -80,7 +82,7 @@ class ApplyRedirects {
this.expandSegmentGroup(this.ngModule, this.config, this.urlTree.root, PRIMARY_OUTLET); this.expandSegmentGroup(this.ngModule, this.config, this.urlTree.root, PRIMARY_OUTLET);
const urlTrees$ = map.call( const urlTrees$ = map.call(
expanded$, (rootSegmentGroup: UrlSegmentGroup) => this.createUrlTree( expanded$, (rootSegmentGroup: UrlSegmentGroup) => this.createUrlTree(
rootSegmentGroup, this.urlTree.queryParams, this.urlTree.fragment)); rootSegmentGroup, this.urlTree.queryParams, this.urlTree.fragment !));
return _catch.call(urlTrees$, (e: any) => { return _catch.call(urlTrees$, (e: any) => {
if (e instanceof AbsoluteRedirect) { if (e instanceof AbsoluteRedirect) {
// after an absolute redirect we do not apply any more redirects! // after an absolute redirect we do not apply any more redirects!
@ -102,7 +104,7 @@ class ApplyRedirects {
this.expandSegmentGroup(this.ngModule, this.config, tree.root, PRIMARY_OUTLET); this.expandSegmentGroup(this.ngModule, this.config, tree.root, PRIMARY_OUTLET);
const mapped$ = map.call( const mapped$ = map.call(
expanded$, (rootSegmentGroup: UrlSegmentGroup) => expanded$, (rootSegmentGroup: UrlSegmentGroup) =>
this.createUrlTree(rootSegmentGroup, tree.queryParams, tree.fragment)); this.createUrlTree(rootSegmentGroup, tree.queryParams, tree.fragment !));
return _catch.call(mapped$, (e: any): Observable<UrlTree> => { return _catch.call(mapped$, (e: any): Observable<UrlTree> => {
if (e instanceof NoMatch) { if (e instanceof NoMatch) {
throw this.noMatchError(e); throw this.noMatchError(e);
@ -215,8 +217,8 @@ class ApplyRedirects {
private expandWildCardWithParamsAgainstRouteUsingRedirect( private expandWildCardWithParamsAgainstRouteUsingRedirect(
ngModule: NgModuleRef<any>, routes: Route[], route: Route, ngModule: NgModuleRef<any>, routes: Route[], route: Route,
outlet: string): Observable<UrlSegmentGroup> { outlet: string): Observable<UrlSegmentGroup> {
const newTree = this.applyRedirectCommands([], route.redirectTo, {}); const newTree = this.applyRedirectCommands([], route.redirectTo !, {});
if (route.redirectTo.startsWith('/')) { if (route.redirectTo !.startsWith('/')) {
return absoluteRedirect(newTree); return absoluteRedirect(newTree);
} }
@ -234,8 +236,8 @@ class ApplyRedirects {
if (!matched) return noMatch(segmentGroup); if (!matched) return noMatch(segmentGroup);
const newTree = this.applyRedirectCommands( const newTree = this.applyRedirectCommands(
consumedSegments, route.redirectTo, <any>positionalParamSegments); consumedSegments, route.redirectTo !, <any>positionalParamSegments);
if (route.redirectTo.startsWith('/')) { if (route.redirectTo !.startsWith('/')) {
return absoluteRedirect(newTree); return absoluteRedirect(newTree);
} }
@ -331,7 +333,7 @@ class ApplyRedirects {
} }
if (c.numberOfChildren > 1 || !c.children[PRIMARY_OUTLET]) { if (c.numberOfChildren > 1 || !c.children[PRIMARY_OUTLET]) {
return namedOutletsRedirect(route.redirectTo); return namedOutletsRedirect(route.redirectTo !);
} }
c = c.children[PRIMARY_OUTLET]; c = c.children[PRIMARY_OUTLET];
@ -442,9 +444,9 @@ function match(segmentGroup: UrlSegmentGroup, route: Route, segments: UrlSegment
return { return {
matched: true, matched: true,
consumedSegments: res.consumed, consumedSegments: res.consumed !,
lastChild: res.consumed.length, lastChild: res.consumed.length !,
positionalParamSegments: res.posParams, positionalParamSegments: res.posParams !,
}; };
} }

View File

@ -164,7 +164,7 @@ function createPositionApplyingDoubleDots(
let dd = numberOfDoubleDots; let dd = numberOfDoubleDots;
while (dd > ci) { while (dd > ci) {
dd -= ci; dd -= ci;
g = g.parent; g = g.parent !;
if (!g) { if (!g) {
throw new Error('Invalid number of \'../\''); throw new Error('Invalid number of \'../\'');
} }

View File

@ -71,8 +71,8 @@ export class RouterOutlet implements OnDestroy {
if (!this.activated) throw new Error('Outlet is not activated'); if (!this.activated) throw new Error('Outlet is not activated');
this.location.detach(); this.location.detach();
const r = this.activated; const r = this.activated;
this.activated = null; this.activated = null !;
this._activatedRoute = null; this._activatedRoute = null !;
return r; return r;
} }
@ -86,8 +86,8 @@ export class RouterOutlet implements OnDestroy {
if (this.activated) { if (this.activated) {
const c = this.component; const c = this.component;
this.activated.destroy(); this.activated.destroy();
this.activated = null; this.activated = null !;
this._activatedRoute = null; this._activatedRoute = null !;
this.deactivateEvents.emit(c); this.deactivateEvents.emit(c);
} }
} }
@ -104,8 +104,8 @@ export class RouterOutlet implements OnDestroy {
this._activatedRoute = activatedRoute; this._activatedRoute = activatedRoute;
const snapshot = activatedRoute._futureSnapshot; const snapshot = activatedRoute._futureSnapshot;
const component: any = <any>snapshot._routeConfig.component; const component: any = <any>snapshot._routeConfig !.component;
const factory = resolver.resolveComponentFactory(component); const factory = resolver.resolveComponentFactory(component) !;
const inj = ReflectiveInjector.fromResolvedProviders(providers, injector); const inj = ReflectiveInjector.fromResolvedProviders(providers, injector);
@ -126,10 +126,10 @@ export class RouterOutlet implements OnDestroy {
this._activatedRoute = activatedRoute; this._activatedRoute = activatedRoute;
const snapshot = activatedRoute._futureSnapshot; const snapshot = activatedRoute._futureSnapshot;
const component = <any>snapshot._routeConfig.component; const component = <any>snapshot._routeConfig !.component;
resolver = resolver || this.resolver; resolver = resolver || this.resolver;
const factory = resolver.resolveComponentFactory(component); const factory = resolver.resolveComponentFactory(component) !;
const injector = new OutletInjector(activatedRoute, outletMap, this.location.injector); const injector = new OutletInjector(activatedRoute, outletMap, this.location.injector);

View File

@ -21,14 +21,14 @@ import {TreeNode} from './utils/tree';
class NoMatch {} class NoMatch {}
export function recognize( export function recognize(
rootComponentType: Type<any>, config: Routes, urlTree: UrlTree, rootComponentType: Type<any>| null, config: Routes, urlTree: UrlTree,
url: string): Observable<RouterStateSnapshot> { url: string): Observable<RouterStateSnapshot> {
return new Recognizer(rootComponentType, config, urlTree, url).recognize(); return new Recognizer(rootComponentType, config, urlTree, url).recognize();
} }
class Recognizer { class Recognizer {
constructor( constructor(
private rootComponentType: Type<any>, private config: Routes, private urlTree: UrlTree, private rootComponentType: Type<any>|null, private config: Routes, private urlTree: UrlTree,
private url: string) {} private url: string) {}
recognize(): Observable<RouterStateSnapshot> { recognize(): Observable<RouterStateSnapshot> {
@ -38,8 +38,8 @@ class Recognizer {
const children = this.processSegmentGroup(this.config, rootSegmentGroup, PRIMARY_OUTLET); const children = this.processSegmentGroup(this.config, rootSegmentGroup, PRIMARY_OUTLET);
const root = new ActivatedRouteSnapshot( const root = new ActivatedRouteSnapshot(
[], Object.freeze({}), Object.freeze(this.urlTree.queryParams), this.urlTree.fragment, {}, [], Object.freeze({}), Object.freeze(this.urlTree.queryParams), this.urlTree.fragment !,
PRIMARY_OUTLET, this.rootComponentType, null, this.urlTree.root, -1, {}); {}, PRIMARY_OUTLET, this.rootComponentType, null, this.urlTree.root, -1, {});
const rootNode = new TreeNode<ActivatedRouteSnapshot>(root, children); const rootNode = new TreeNode<ActivatedRouteSnapshot>(root, children);
const routeState = new RouterStateSnapshot(this.url, rootNode); const routeState = new RouterStateSnapshot(this.url, rootNode);
@ -110,10 +110,10 @@ class Recognizer {
if ((route.outlet || PRIMARY_OUTLET) !== outlet) throw new NoMatch(); if ((route.outlet || PRIMARY_OUTLET) !== outlet) throw new NoMatch();
if (route.path === '**') { if (route.path === '**') {
const params = segments.length > 0 ? last(segments).parameters : {}; const params = segments.length > 0 ? last(segments) !.parameters : {};
const snapshot = new ActivatedRouteSnapshot( const snapshot = new ActivatedRouteSnapshot(
segments, params, Object.freeze(this.urlTree.queryParams), this.urlTree.fragment, segments, params, Object.freeze(this.urlTree.queryParams), this.urlTree.fragment !,
getData(route), outlet, route.component, route, getSourceSegmentGroup(rawSegment), getData(route), outlet, route.component !, route, getSourceSegmentGroup(rawSegment),
getPathIndexShift(rawSegment) + segments.length, getResolve(route)); getPathIndexShift(rawSegment) + segments.length, getResolve(route));
return [new TreeNode<ActivatedRouteSnapshot>(snapshot, [])]; return [new TreeNode<ActivatedRouteSnapshot>(snapshot, [])];
} }
@ -127,7 +127,7 @@ class Recognizer {
const snapshot = new ActivatedRouteSnapshot( const snapshot = new ActivatedRouteSnapshot(
consumedSegments, parameters, Object.freeze(this.urlTree.queryParams), consumedSegments, parameters, Object.freeze(this.urlTree.queryParams),
this.urlTree.fragment, getData(route), outlet, route.component, route, this.urlTree.fragment !, getData(route), outlet, route.component !, route,
getSourceSegmentGroup(rawSegment), getPathIndexShift(rawSegment) + consumedSegments.length, getSourceSegmentGroup(rawSegment), getPathIndexShift(rawSegment) + consumedSegments.length,
getResolve(route)); getResolve(route));
@ -160,7 +160,7 @@ function getChildConfig(route: Route): Route[] {
} }
if (route.loadChildren) { if (route.loadChildren) {
return route._loadedConfig.routes; return route._loadedConfig !.routes;
} }
return []; return [];
@ -180,7 +180,7 @@ function match(segmentGroup: UrlSegmentGroup, route: Route, segments: UrlSegment
if (!res) throw new NoMatch(); if (!res) throw new NoMatch();
const posParams: {[n: string]: string} = {}; const posParams: {[n: string]: string} = {};
forEach(res.posParams, (v: UrlSegment, k: string) => { posParams[k] = v.path; }); forEach(res.posParams !, (v: UrlSegment, k: string) => { posParams[k] = v.path; });
const parameters = {...posParams, ...res.consumed[res.consumed.length - 1].parameters}; const parameters = {...posParams, ...res.consumed[res.consumed.length - 1].parameters};
return {consumedSegments: res.consumed, lastChild: res.consumed.length, parameters}; return {consumedSegments: res.consumed, lastChild: res.consumed.length, parameters};

View File

@ -37,13 +37,13 @@ export abstract class RouteReuseStrategy {
abstract shouldDetach(route: ActivatedRouteSnapshot): boolean; abstract shouldDetach(route: ActivatedRouteSnapshot): boolean;
/** Stores the detached route */ /** Stores the detached route */
abstract store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): void; abstract store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle|null): void;
/** Determines if this route (and its subtree) should be reattached */ /** Determines if this route (and its subtree) should be reattached */
abstract shouldAttach(route: ActivatedRouteSnapshot): boolean; abstract shouldAttach(route: ActivatedRouteSnapshot): boolean;
/** Retrieves the previously stored route */ /** Retrieves the previously stored route */
abstract retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle; abstract retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle|null;
/** Determines if a route should be reused */ /** Determines if a route should be reused */
abstract shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean; abstract shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean;

View File

@ -189,7 +189,7 @@ export type RouterHook = (snapshot: RouterStateSnapshot) => Observable<void>;
* @internal * @internal
*/ */
function defaultRouterHook(snapshot: RouterStateSnapshot): Observable<void> { function defaultRouterHook(snapshot: RouterStateSnapshot): Observable<void> {
return of (null); return of (null) as any;
} }
/** /**
@ -199,7 +199,7 @@ export class DefaultRouteReuseStrategy implements RouteReuseStrategy {
shouldDetach(route: ActivatedRouteSnapshot): boolean { return false; } shouldDetach(route: ActivatedRouteSnapshot): boolean { return false; }
store(route: ActivatedRouteSnapshot, detachedTree: DetachedRouteHandle): void {} store(route: ActivatedRouteSnapshot, detachedTree: DetachedRouteHandle): void {}
shouldAttach(route: ActivatedRouteSnapshot): boolean { return false; } shouldAttach(route: ActivatedRouteSnapshot): boolean { return false; }
retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle { return null; } retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle|null { return null; }
shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean { shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
return future.routeConfig === curr.routeConfig; return future.routeConfig === curr.routeConfig;
} }
@ -218,7 +218,7 @@ export class Router {
private currentUrlTree: UrlTree; private currentUrlTree: UrlTree;
private rawUrlTree: UrlTree; private rawUrlTree: UrlTree;
private navigations = new BehaviorSubject<NavigationParams>(null); private navigations = new BehaviorSubject<NavigationParams>(null !);
private routerEvents = new Subject<Event>(); private routerEvents = new Subject<Event>();
private currentRouterState: RouterState; private currentRouterState: RouterState;
@ -263,7 +263,7 @@ export class Router {
*/ */
// TODO: vsavkin make internal after the final is out. // TODO: vsavkin make internal after the final is out.
constructor( constructor(
private rootComponentType: Type<any>, private urlSerializer: UrlSerializer, private rootComponentType: Type<any>|null, private urlSerializer: UrlSerializer,
private outletMap: RouterOutletMap, private location: Location, injector: Injector, private outletMap: RouterOutletMap, private location: Location, injector: Injector,
loader: NgModuleFactoryLoader, compiler: Compiler, public config: Routes) { loader: NgModuleFactoryLoader, compiler: Compiler, public config: Routes) {
const onLoadStart = (r: Route) => this.triggerEvent(new RouteConfigLoadStart(r)); const onLoadStart = (r: Route) => this.triggerEvent(new RouteConfigLoadStart(r));
@ -354,7 +354,7 @@ export class Router {
dispose(): void { dispose(): void {
if (this.locationSubscription) { if (this.locationSubscription) {
this.locationSubscription.unsubscribe(); this.locationSubscription.unsubscribe();
this.locationSubscription = null; this.locationSubscription = null !;
} }
} }
@ -407,7 +407,7 @@ export class Router {
} }
const a = relativeTo || this.routerState.root; const a = relativeTo || this.routerState.root;
const f = preserveFragment ? this.currentUrlTree.fragment : fragment; const f = preserveFragment ? this.currentUrlTree.fragment : fragment;
let q: Params = null; let q: Params|null = null;
if (queryParamsHandling) { if (queryParamsHandling) {
switch (queryParamsHandling) { switch (queryParamsHandling) {
case 'merge': case 'merge':
@ -417,12 +417,12 @@ export class Router {
q = this.currentUrlTree.queryParams; q = this.currentUrlTree.queryParams;
break; break;
default: default:
q = queryParams; q = queryParams || null;
} }
} else { } else {
q = preserveQueryParams ? this.currentUrlTree.queryParams : queryParams; q = preserveQueryParams ? this.currentUrlTree.queryParams : queryParams || null;
} }
return createUrlTree(a, this.currentUrlTree, commands, q, f); return createUrlTree(a, this.currentUrlTree, commands, q !, f !);
} }
/** /**
@ -535,7 +535,7 @@ export class Router {
// we should skip those. // we should skip those.
if (lastNavigation && source !== 'imperative' && lastNavigation.source === 'imperative' && if (lastNavigation && source !== 'imperative' && lastNavigation.source === 'imperative' &&
lastNavigation.rawUrl.toString() === rawUrl.toString()) { lastNavigation.rawUrl.toString() === rawUrl.toString()) {
return null; // return value is not used return Promise.resolve(true); // return value is not used
} }
// Because of a bug in IE and Edge, the location class fires two events (popstate and // Because of a bug in IE and Edge, the location class fires two events (popstate and
@ -543,7 +543,7 @@ export class Router {
// flicker. // flicker.
if (lastNavigation && source == 'hashchange' && lastNavigation.source === 'popstate' && if (lastNavigation && source == 'hashchange' && lastNavigation.source === 'popstate' &&
lastNavigation.rawUrl.toString() === rawUrl.toString()) { lastNavigation.rawUrl.toString() === rawUrl.toString()) {
return null; // return value is not used return Promise.resolve(true); // return value is not used
} }
let resolve: any = null; let resolve: any = null;
@ -572,7 +572,7 @@ export class Router {
Promise.resolve() Promise.resolve()
.then( .then(
(_) => this.runNavigate( (_) => this.runNavigate(
url, rawUrl, extras.skipLocationChange, extras.replaceUrl, id, null)) url, rawUrl, !!extras.skipLocationChange, !!extras.replaceUrl, id, null))
.then(resolve, reject); .then(resolve, reject);
// we cannot process the current URL, but we could process the previous one => // we cannot process the current URL, but we could process the previous one =>
@ -596,7 +596,7 @@ export class Router {
private runNavigate( private runNavigate(
url: UrlTree, rawUrl: UrlTree, shouldPreventPushState: boolean, shouldReplaceUrl: boolean, url: UrlTree, rawUrl: UrlTree, shouldPreventPushState: boolean, shouldReplaceUrl: boolean,
id: number, precreatedState: RouterStateSnapshot): Promise<boolean> { id: number, precreatedState: RouterStateSnapshot|null): Promise<boolean> {
if (id !== this.navigationId) { if (id !== this.navigationId) {
this.location.go(this.urlSerializer.serialize(this.currentUrlTree)); this.location.go(this.urlSerializer.serialize(this.currentUrlTree));
this.routerEvents.next(new NavigationCancel( this.routerEvents.next(new NavigationCancel(
@ -768,7 +768,7 @@ class CanActivate {
} }
class CanDeactivate { class CanDeactivate {
constructor(public component: Object, public route: ActivatedRouteSnapshot) {} constructor(public component: Object|null, public route: ActivatedRouteSnapshot) {}
} }
@ -804,8 +804,8 @@ export class PreActivation {
} }
private traverseChildRoutes( private traverseChildRoutes(
futureNode: TreeNode<ActivatedRouteSnapshot>, currNode: TreeNode<ActivatedRouteSnapshot>, futureNode: TreeNode<ActivatedRouteSnapshot>, currNode: TreeNode<ActivatedRouteSnapshot>|null,
outletMap: RouterOutletMap, futurePath: ActivatedRouteSnapshot[]): void { outletMap: RouterOutletMap|null, futurePath: ActivatedRouteSnapshot[]): void {
const prevChildren = nodeChildrenAsMap(currNode); const prevChildren = nodeChildrenAsMap(currNode);
futureNode.children.forEach(c => { futureNode.children.forEach(c => {
@ -814,12 +814,12 @@ export class PreActivation {
}); });
forEach( forEach(
prevChildren, (v: TreeNode<ActivatedRouteSnapshot>, k: string) => prevChildren, (v: TreeNode<ActivatedRouteSnapshot>, k: string) =>
this.deactiveRouteAndItsChildren(v, outletMap._outlets[k])); this.deactiveRouteAndItsChildren(v, outletMap !._outlets[k]));
} }
private traverseRoutes( private traverseRoutes(
futureNode: TreeNode<ActivatedRouteSnapshot>, currNode: TreeNode<ActivatedRouteSnapshot>, futureNode: TreeNode<ActivatedRouteSnapshot>, currNode: TreeNode<ActivatedRouteSnapshot>,
parentOutletMap: RouterOutletMap, futurePath: ActivatedRouteSnapshot[]): void { parentOutletMap: RouterOutletMap|null, futurePath: ActivatedRouteSnapshot[]): void {
const future = futureNode.value; const future = futureNode.value;
const curr = currNode ? currNode.value : null; const curr = currNode ? currNode.value : null;
const outlet = parentOutletMap ? parentOutletMap._outlets[futureNode.value.outlet] : null; const outlet = parentOutletMap ? parentOutletMap._outlets[futureNode.value.outlet] : null;
@ -827,9 +827,9 @@ export class PreActivation {
// reusing the node // reusing the node
if (curr && future._routeConfig === curr._routeConfig) { if (curr && future._routeConfig === curr._routeConfig) {
if (this.shouldRunGuardsAndResolvers( if (this.shouldRunGuardsAndResolvers(
curr, future, future._routeConfig.runGuardsAndResolvers)) { curr, future, future._routeConfig !.runGuardsAndResolvers)) {
this.canActivateChecks.push(new CanActivate(futurePath)); this.canActivateChecks.push(new CanActivate(futurePath));
this.canDeactivateChecks.push(new CanDeactivate(outlet.component, curr)); this.canDeactivateChecks.push(new CanDeactivate(outlet !.component, curr));
} else { } else {
// we need to set the data // we need to set the data
future.data = curr.data; future.data = curr.data;
@ -864,7 +864,7 @@ export class PreActivation {
private shouldRunGuardsAndResolvers( private shouldRunGuardsAndResolvers(
curr: ActivatedRouteSnapshot, future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot, future: ActivatedRouteSnapshot,
mode: RunGuardsAndResolvers): boolean { mode: RunGuardsAndResolvers|undefined): boolean {
switch (mode) { switch (mode) {
case 'always': case 'always':
return true; return true;
@ -880,7 +880,7 @@ export class PreActivation {
} }
private deactiveRouteAndItsChildren( private deactiveRouteAndItsChildren(
route: TreeNode<ActivatedRouteSnapshot>, outlet: RouterOutlet): void { route: TreeNode<ActivatedRouteSnapshot>, outlet: RouterOutlet|null): void {
const prevChildren = nodeChildrenAsMap(route); const prevChildren = nodeChildrenAsMap(route);
const r = route.value; const r = route.value;
@ -958,13 +958,14 @@ export class PreActivation {
} }
private extractCanActivateChild(p: ActivatedRouteSnapshot): private extractCanActivateChild(p: ActivatedRouteSnapshot):
{node: ActivatedRouteSnapshot, guards: any[]} { {node: ActivatedRouteSnapshot, guards: any[]}|null {
const canActivateChild = p._routeConfig ? p._routeConfig.canActivateChild : null; const canActivateChild = p._routeConfig ? p._routeConfig.canActivateChild : null;
if (!canActivateChild || canActivateChild.length === 0) return null; if (!canActivateChild || canActivateChild.length === 0) return null;
return {node: p, guards: canActivateChild}; return {node: p, guards: canActivateChild};
} }
private runCanDeactivate(component: Object, curr: ActivatedRouteSnapshot): Observable<boolean> { private runCanDeactivate(component: Object|null, curr: ActivatedRouteSnapshot):
Observable<boolean> {
const canDeactivate = curr && curr._routeConfig ? curr._routeConfig.canDeactivate : null; const canDeactivate = curr && curr._routeConfig ? curr._routeConfig.canDeactivate : null;
if (!canDeactivate || canDeactivate.length === 0) return of (true); if (!canDeactivate || canDeactivate.length === 0) return of (true);
const canDeactivate$ = mergeMap.call(from(canDeactivate), (c: any) => { const canDeactivate$ = mergeMap.call(from(canDeactivate), (c: any) => {
@ -1020,7 +1021,7 @@ class ActivateRoutes {
} }
private deactivateChildRoutes( private deactivateChildRoutes(
futureNode: TreeNode<ActivatedRoute>, currNode: TreeNode<ActivatedRoute>, futureNode: TreeNode<ActivatedRoute>, currNode: TreeNode<ActivatedRoute>|null,
outletMap: RouterOutletMap): void { outletMap: RouterOutletMap): void {
const prevChildren: {[key: string]: any} = nodeChildrenAsMap(currNode); const prevChildren: {[key: string]: any} = nodeChildrenAsMap(currNode);
futureNode.children.forEach(c => { futureNode.children.forEach(c => {
@ -1031,7 +1032,7 @@ class ActivateRoutes {
} }
private activateChildRoutes( private activateChildRoutes(
futureNode: TreeNode<ActivatedRoute>, currNode: TreeNode<ActivatedRoute>, futureNode: TreeNode<ActivatedRoute>, currNode: TreeNode<ActivatedRoute>|null,
outletMap: RouterOutletMap): void { outletMap: RouterOutletMap): void {
const prevChildren: {[key: string]: any} = nodeChildrenAsMap(currNode); const prevChildren: {[key: string]: any} = nodeChildrenAsMap(currNode);
futureNode.children.forEach( futureNode.children.forEach(
@ -1136,7 +1137,7 @@ class ActivateRoutes {
private deactiveRouteAndOutlet(route: TreeNode<ActivatedRoute>, parentOutletMap: RouterOutletMap): private deactiveRouteAndOutlet(route: TreeNode<ActivatedRoute>, parentOutletMap: RouterOutletMap):
void { void {
const prevChildren: {[key: string]: any} = nodeChildrenAsMap(route); const prevChildren: {[key: string]: any} = nodeChildrenAsMap(route);
let outlet: RouterOutlet = null; let outlet: RouterOutlet|null = null;
// getOutlet throws when cannot find the right outlet, // getOutlet throws when cannot find the right outlet,
// which can happen if an outlet was in an NgIf and was removed // which can happen if an outlet was in an NgIf and was removed
@ -1166,7 +1167,7 @@ function advanceActivatedRouteNodeAndItsChildren(node: TreeNode<ActivatedRoute>)
node.children.forEach(advanceActivatedRouteNodeAndItsChildren); node.children.forEach(advanceActivatedRouteNodeAndItsChildren);
} }
function parentLoadedConfig(snapshot: ActivatedRouteSnapshot): LoadedRouterConfig { function parentLoadedConfig(snapshot: ActivatedRouteSnapshot): LoadedRouterConfig|null {
for (let s = snapshot.parent; s; s = s.parent) { for (let s = snapshot.parent; s; s = s.parent) {
const route = s._routeConfig; const route = s._routeConfig;
if (route && route._loadedConfig) return route._loadedConfig; if (route && route._loadedConfig) return route._loadedConfig;
@ -1176,7 +1177,7 @@ function parentLoadedConfig(snapshot: ActivatedRouteSnapshot): LoadedRouterConfi
return null; return null;
} }
function closestLoadedConfig(snapshot: ActivatedRouteSnapshot): LoadedRouterConfig { function closestLoadedConfig(snapshot: ActivatedRouteSnapshot): LoadedRouterConfig|null {
if (!snapshot) return null; if (!snapshot) return null;
for (let s = snapshot.parent; s; s = s.parent) { for (let s = snapshot.parent; s; s = s.parent) {
@ -1187,7 +1188,7 @@ function closestLoadedConfig(snapshot: ActivatedRouteSnapshot): LoadedRouterConf
return null; return null;
} }
function nodeChildrenAsMap<T extends{outlet: string}>(node: TreeNode<T>) { function nodeChildrenAsMap<T extends{outlet: string}>(node: TreeNode<T>| null) {
const map: {[key: string]: TreeNode<T>} = {}; const map: {[key: string]: TreeNode<T>} = {};
if (node) { if (node) {

View File

@ -32,7 +32,7 @@ export class RouterConfigLoader {
this.onLoadStartListener(route); this.onLoadStartListener(route);
} }
const moduleFactory$ = this.loadModuleFactory(route.loadChildren); const moduleFactory$ = this.loadModuleFactory(route.loadChildren !);
return map.call(moduleFactory$, (factory: NgModuleFactory<any>) => { return map.call(moduleFactory$, (factory: NgModuleFactory<any>) => {
if (this.onLoadEndListener) { if (this.onLoadEndListener) {

View File

@ -327,7 +327,7 @@ export class RouterInitializer {
appInitializer(): Promise<any> { appInitializer(): Promise<any> {
const p: Promise<any> = this.injector.get(LOCATION_INITIALIZED, Promise.resolve(null)); const p: Promise<any> = this.injector.get(LOCATION_INITIALIZED, Promise.resolve(null));
return p.then(() => { return p.then(() => {
let resolve: Function = null; let resolve: Function = null !;
const res = new Promise(r => resolve = r); const res = new Promise(r => resolve = r);
const router = this.injector.get(Router); const router = this.injector.get(Router);
const opts = this.injector.get(ROUTER_CONFIGURATION); const opts = this.injector.get(ROUTER_CONFIGURATION);
@ -349,7 +349,7 @@ export class RouterInitializer {
// subsequent navigations should not be delayed // subsequent navigations should not be delayed
} else { } else {
return of (null); return of (null) as any;
} }
}; };
router.initialNavigation(); router.initialNavigation();
@ -380,7 +380,7 @@ export class RouterInitializer {
preloader.setUpPreloading(); preloader.setUpPreloading();
router.resetRootComponentType(ref.componentTypes[0]); router.resetRootComponentType(ref.componentTypes[0]);
this.resultOfPreactivationDone.next(null); this.resultOfPreactivationDone.next(null !);
this.resultOfPreactivationDone.complete(); this.resultOfPreactivationDone.complete();
} }

View File

@ -25,5 +25,5 @@ export class RouterOutletMap {
/** /**
* Removes an outlet from this map. * Removes an outlet from this map.
*/ */
removeOutlet(name: string): void { this._outlets[name] = undefined; } removeOutlet(name: string): void { this._outlets[name] = undefined !; }
} }

View File

@ -57,7 +57,7 @@ export class RouterState extends Tree<ActivatedRoute> {
toString(): string { return this.snapshot.toString(); } toString(): string { return this.snapshot.toString(); }
} }
export function createEmptyState(urlTree: UrlTree, rootComponent: Type<any>): RouterState { export function createEmptyState(urlTree: UrlTree, rootComponent: Type<any>| null): RouterState {
const snapshot = createEmptyStateSnapshot(urlTree, rootComponent); const snapshot = createEmptyStateSnapshot(urlTree, rootComponent);
const emptyUrl = new BehaviorSubject([new UrlSegment('', {})]); const emptyUrl = new BehaviorSubject([new UrlSegment('', {})]);
const emptyParams = new BehaviorSubject({}); const emptyParams = new BehaviorSubject({});
@ -72,7 +72,7 @@ export function createEmptyState(urlTree: UrlTree, rootComponent: Type<any>): Ro
} }
export function createEmptyStateSnapshot( export function createEmptyStateSnapshot(
urlTree: UrlTree, rootComponent: Type<any>): RouterStateSnapshot { urlTree: UrlTree, rootComponent: Type<any>| null): RouterStateSnapshot {
const emptyParams = {}; const emptyParams = {};
const emptyData = {}; const emptyData = {};
const emptyQueryParams = {}; const emptyQueryParams = {};
@ -132,21 +132,21 @@ export class ActivatedRoute {
public outlet: string, public outlet: string,
/** The component of the route. It's a constant */ /** The component of the route. It's a constant */
// TODO(vsavkin): remove |string // TODO(vsavkin): remove |string
public component: Type<any>|string, futureSnapshot: ActivatedRouteSnapshot) { public component: Type<any>|string|null, futureSnapshot: ActivatedRouteSnapshot) {
this._futureSnapshot = futureSnapshot; this._futureSnapshot = futureSnapshot;
} }
/** The configuration used to match this route */ /** The configuration used to match this route */
get routeConfig(): Route { return this._futureSnapshot.routeConfig; } get routeConfig(): Route|null { return this._futureSnapshot.routeConfig; }
/** The root of the router state */ /** The root of the router state */
get root(): ActivatedRoute { return this._routerState.root; } get root(): ActivatedRoute { return this._routerState.root; }
/** The parent of this route in the router state tree */ /** The parent of this route in the router state tree */
get parent(): ActivatedRoute { return this._routerState.parent(this); } get parent(): ActivatedRoute|null { return this._routerState.parent(this); }
/** The first child of this route in the router state tree */ /** The first child of this route in the router state tree */
get firstChild(): ActivatedRoute { return this._routerState.firstChild(this); } get firstChild(): ActivatedRoute|null { return this._routerState.firstChild(this); }
/** The children of this route in the router state tree */ /** The children of this route in the router state tree */
get children(): ActivatedRoute[] { return this._routerState.children(this); } get children(): ActivatedRoute[] { return this._routerState.children(this); }
@ -234,7 +234,7 @@ export function inheritedParamsDataResolve(route: ActivatedRouteSnapshot): Inher
*/ */
export class ActivatedRouteSnapshot { export class ActivatedRouteSnapshot {
/** @internal **/ /** @internal **/
_routeConfig: Route; _routeConfig: Route|null;
/** @internal **/ /** @internal **/
_urlSegment: UrlSegmentGroup; _urlSegment: UrlSegmentGroup;
/** @internal */ /** @internal */
@ -265,7 +265,7 @@ export class ActivatedRouteSnapshot {
/** The outlet name of the route */ /** The outlet name of the route */
public outlet: string, public outlet: string,
/** The component of the route */ /** The component of the route */
public component: Type<any>|string, routeConfig: Route, urlSegment: UrlSegmentGroup, public component: Type<any>|string|null, routeConfig: Route|null, urlSegment: UrlSegmentGroup,
lastPathIndex: number, resolve: ResolveData) { lastPathIndex: number, resolve: ResolveData) {
this._routeConfig = routeConfig; this._routeConfig = routeConfig;
this._urlSegment = urlSegment; this._urlSegment = urlSegment;
@ -274,16 +274,16 @@ export class ActivatedRouteSnapshot {
} }
/** The configuration used to match this route */ /** The configuration used to match this route */
get routeConfig(): Route { return this._routeConfig; } get routeConfig(): Route|null { return this._routeConfig; }
/** The root of the router state */ /** The root of the router state */
get root(): ActivatedRouteSnapshot { return this._routerState.root; } get root(): ActivatedRouteSnapshot { return this._routerState.root; }
/** The parent of this route in the router state tree */ /** The parent of this route in the router state tree */
get parent(): ActivatedRouteSnapshot { return this._routerState.parent(this); } get parent(): ActivatedRouteSnapshot|null { return this._routerState.parent(this); }
/** The first child of this route in the router state tree */ /** The first child of this route in the router state tree */
get firstChild(): ActivatedRouteSnapshot { return this._routerState.firstChild(this); } get firstChild(): ActivatedRouteSnapshot|null { return this._routerState.firstChild(this); }
/** The children of this route in the router state tree */ /** The children of this route in the router state tree */
get children(): ActivatedRouteSnapshot[] { return this._routerState.children(this); } get children(): ActivatedRouteSnapshot[] { return this._routerState.children(this); }
@ -398,5 +398,5 @@ export function equalParamsAndUrlSegments(
const parentsMismatch = !a.parent !== !b.parent; const parentsMismatch = !a.parent !== !b.parent;
return equalUrlParams && !parentsMismatch && return equalUrlParams && !parentsMismatch &&
(!a.parent || equalParamsAndUrlSegments(a.parent, b.parent)); (!a.parent || equalParamsAndUrlSegments(a.parent, b.parent !));
} }

View File

@ -111,7 +111,7 @@ export function isNavigationCancelingError(error: Error) {
// Matches the route configuration (`route`) against the actual URL (`segments`). // Matches the route configuration (`route`) against the actual URL (`segments`).
export function defaultUrlMatcher( export function defaultUrlMatcher(
segments: UrlSegment[], segmentGroup: UrlSegmentGroup, route: Route): UrlMatchResult|null { segments: UrlSegment[], segmentGroup: UrlSegmentGroup, route: Route): UrlMatchResult|null {
const parts = route.path.split('/'); const parts = route.path !.split('/');
if (parts.length > segments.length) { if (parts.length > segments.length) {
// The actual URL is shorter than the config, no match // The actual URL is shorter than the config, no match

View File

@ -113,7 +113,7 @@ export class UrlTree {
/** The query params of the URL */ /** The query params of the URL */
public queryParams: {[key: string]: string}, public queryParams: {[key: string]: string},
/** The fragment of the URL */ /** The fragment of the URL */
public fragment: string) {} public fragment: string|null) {}
get queryParamMap(): ParamMap { get queryParamMap(): ParamMap {
if (!this._queryParamMap) { if (!this._queryParamMap) {
@ -139,7 +139,7 @@ export class UrlSegmentGroup {
/** @internal */ /** @internal */
_segmentIndexShift: number; _segmentIndexShift: number;
/** The parent node in the url tree */ /** The parent node in the url tree */
parent: UrlSegmentGroup = null; parent: UrlSegmentGroup|null = null;
constructor( constructor(
/** The URL segments of this group. See {@link UrlSegment} for more information */ /** The URL segments of this group. See {@link UrlSegment} for more information */
@ -280,7 +280,7 @@ export class DefaultUrlSerializer implements UrlSerializer {
serialize(tree: UrlTree): string { serialize(tree: UrlTree): string {
const segment = `/${serializeSegment(tree.root, true)}`; const segment = `/${serializeSegment(tree.root, true)}`;
const query = serializeQueryParams(tree.queryParams); const query = serializeQueryParams(tree.queryParams);
const fragment = typeof tree.fragment === `string` ? `#${encodeURI(tree.fragment)}` : ''; const fragment = typeof tree.fragment === `string` ? `#${encodeURI(tree.fragment !)}` : '';
return `${segment}${query}${fragment}`; return `${segment}${query}${fragment}`;
} }
@ -397,7 +397,9 @@ class UrlParser {
return params; return params;
} }
parseFragment(): string { return this.consumeOptional('#') ? decodeURI(this.remaining) : null; } parseFragment(): string|null {
return this.consumeOptional('#') ? decodeURI(this.remaining) : null;
}
private parseChildren(): {[outlet: string]: UrlSegmentGroup} { private parseChildren(): {[outlet: string]: UrlSegmentGroup} {
if (this.remaining === '') { if (this.remaining === '') {
@ -521,7 +523,7 @@ class UrlParser {
throw new Error(`Cannot parse url '${this.url}'`); throw new Error(`Cannot parse url '${this.url}'`);
} }
let outletName: string; let outletName: string = undefined !;
if (path.indexOf(':') > -1) { if (path.indexOf(':') > -1) {
outletName = path.substr(0, path.indexOf(':')); outletName = path.substr(0, path.indexOf(':'));
this.capture(outletName); this.capture(outletName);

View File

@ -45,7 +45,7 @@ export function flatten<T>(arr: T[][]): T[] {
return Array.prototype.concat.apply([], arr); return Array.prototype.concat.apply([], arr);
} }
export function last<T>(a: T[]): T { export function last<T>(a: T[]): T|null {
return a.length > 0 ? a[a.length - 1] : null; return a.length > 0 ? a[a.length - 1] : null;
} }

View File

@ -17,7 +17,7 @@ export class Tree<T> {
/** /**
* @internal * @internal
*/ */
parent(t: T): T { parent(t: T): T|null {
const p = this.pathFromRoot(t); const p = this.pathFromRoot(t);
return p.length > 1 ? p[p.length - 2] : null; return p.length > 1 ? p[p.length - 2] : null;
} }
@ -33,7 +33,7 @@ export class Tree<T> {
/** /**
* @internal * @internal
*/ */
firstChild(t: T): T { firstChild(t: T): T|null {
const n = findNode(t, this._root); const n = findNode(t, this._root);
return n && n.children.length > 0 ? n.children[0].value : null; return n && n.children.length > 0 ? n.children[0].value : null;
} }
@ -55,7 +55,7 @@ export class Tree<T> {
pathFromRoot(t: T): T[] { return findPath(t, this._root, []).map(s => s.value); } pathFromRoot(t: T): T[] { return findPath(t, this._root, []).map(s => s.value); }
} }
function findNode<T>(expected: T, c: TreeNode<T>): TreeNode<T> { function findNode<T>(expected: T, c: TreeNode<T>): TreeNode<T>|null {
if (expected === c.value) return c; if (expected === c.value) return c;
for (const cc of c.children) { for (const cc of c.children) {
const r = findNode(expected, cc); const r = findNode(expected, cc);

View File

@ -51,7 +51,7 @@ describe('applyRedirects', () => {
}); });
it('should throw when cannot handle a positional parameter', () => { it('should throw when cannot handle a positional parameter', () => {
applyRedirects(testModule.injector, null, serializer, tree('/a/1'), [ applyRedirects(testModule.injector, null !, serializer, tree('/a/1'), [
{path: 'a/:id', redirectTo: 'a/:other'} {path: 'a/:id', redirectTo: 'a/:other'}
]).subscribe(() => {}, (e) => { ]).subscribe(() => {}, (e) => {
expect(e.message).toEqual('Cannot redirect to \'a/:other\'. Cannot find \':other\'.'); expect(e.message).toEqual('Cannot redirect to \'a/:other\'. Cannot find \':other\'.');
@ -403,7 +403,7 @@ describe('applyRedirects', () => {
{path: '', redirectTo: 'a', pathMatch: 'full'} {path: '', redirectTo: 'a', pathMatch: 'full'}
]; ];
applyRedirects(testModule.injector, null, serializer, tree('b'), config) applyRedirects(testModule.injector, null !, serializer, tree('b'), config)
.subscribe( .subscribe(
(_) => { throw 'Should not be reached'; }, (_) => { throw 'Should not be reached'; },
e => { expect(e.message).toEqual('Cannot match any routes. URL Segment: \'b\''); }); e => { expect(e.message).toEqual('Cannot match any routes. URL Segment: \'b\''); });
@ -533,7 +533,7 @@ describe('applyRedirects', () => {
] ]
}]; }];
applyRedirects(testModule.injector, null, serializer, tree('a/(d//aux:e)'), config) applyRedirects(testModule.injector, null !, serializer, tree('a/(d//aux:e)'), config)
.subscribe( .subscribe(
(_) => { throw 'Should not be reached'; }, (_) => { throw 'Should not be reached'; },
e => { expect(e.message).toEqual('Cannot match any routes. URL Segment: \'a\''); }); e => { expect(e.message).toEqual('Cannot match any routes. URL Segment: \'a\''); });
@ -564,7 +564,7 @@ describe('applyRedirects', () => {
it('should error when no children matching and some url is left', () => { it('should error when no children matching and some url is left', () => {
applyRedirects( applyRedirects(
testModule.injector, null, serializer, tree('/a/c'), testModule.injector, null !, serializer, tree('/a/c'),
[{path: 'a', component: ComponentA, children: [{path: 'b', component: ComponentB}]}]) [{path: 'a', component: ComponentA, children: [{path: 'b', component: ComponentB}]}])
.subscribe( .subscribe(
(_) => { throw 'Should not be reached'; }, (_) => { throw 'Should not be reached'; },
@ -587,7 +587,7 @@ describe('applyRedirects', () => {
matcher: matcher, matcher: matcher,
component: ComponentA, component: ComponentA,
children: [{path: 'b', component: ComponentB}] children: [{path: 'b', component: ComponentB}]
}], }] as any,
'/a/1/b', (t: UrlTree) => { compareTrees(t, tree('a/1/b')); }); '/a/1/b', (t: UrlTree) => { compareTrees(t, tree('a/1/b')); });
}); });
}); });
@ -614,7 +614,7 @@ describe('applyRedirects', () => {
it('should throw when using non-absolute redirects', () => { it('should throw when using non-absolute redirects', () => {
applyRedirects( applyRedirects(
testModule.injector, null, serializer, tree('a'), testModule.injector, null !, serializer, tree('a'),
[ [
{path: 'a', redirectTo: 'b(aux:c)'}, {path: 'a', redirectTo: 'b(aux:c)'},
]) ])
@ -629,7 +629,7 @@ describe('applyRedirects', () => {
}); });
function checkRedirect(config: Routes, url: string, callback: any): void { function checkRedirect(config: Routes, url: string, callback: any): void {
applyRedirects(TestBed, null, new DefaultUrlSerializer(), tree(url), config) applyRedirects(TestBed, null !, new DefaultUrlSerializer(), tree(url), config)
.subscribe(callback, e => { throw e; }); .subscribe(callback, e => { throw e; });
} }

View File

@ -16,7 +16,7 @@ import {NavigationEnd, Resolve, Router, RouterModule} from '@angular/router';
describe('bootstrap', () => { describe('bootstrap', () => {
let log: any[] = []; let log: any[] = [];
let testProviders: any[] = null; let testProviders: any[] = null !;
@Component({selector: 'test-app', template: 'root <router-outlet></router-outlet>'}) @Component({selector: 'test-app', template: 'root <router-outlet></router-outlet>'})
class RootCmp { class RootCmp {
@ -80,7 +80,7 @@ describe('bootstrap', () => {
platformBrowserDynamic([]).bootstrapModule(TestModule).then(res => { platformBrowserDynamic([]).bootstrapModule(TestModule).then(res => {
const router = res.injector.get(Router); const router = res.injector.get(Router);
const data = router.routerState.snapshot.root.firstChild.data; const data = router.routerState.snapshot.root.firstChild !.data;
expect(data['test']).toEqual('test-data'); expect(data['test']).toEqual('test-data');
expect(log).toEqual( expect(log).toEqual(
['TestModule', 'NavigationStart', 'RoutesRecognized', 'RootCmp', 'NavigationEnd']); ['TestModule', 'NavigationStart', 'RoutesRecognized', 'RootCmp', 'NavigationEnd']);

View File

@ -24,7 +24,8 @@ describe('config', () => {
it('should throw for undefined route', () => { it('should throw for undefined route', () => {
expect(() => { expect(() => {
validateConfig([{path: 'a', component: ComponentA}, , {path: 'b', component: ComponentB}]); validateConfig(
[{path: 'a', component: ComponentA}, , {path: 'b', component: ComponentB}] as any);
}).toThrowError(/Invalid configuration of route ''/); }).toThrowError(/Invalid configuration of route ''/);
}); });
@ -36,7 +37,7 @@ describe('config', () => {
{path: 'b', component: ComponentB}, {path: 'b', component: ComponentB},
, ,
] ]
}]); }] as any);
}).toThrowError(/Invalid configuration of route 'a'/); }).toThrowError(/Invalid configuration of route 'a'/);
}); });
@ -98,7 +99,7 @@ describe('config', () => {
}); });
it('should throw when path and matcher are missing', () => { it('should throw when path and matcher are missing', () => {
expect(() => { validateConfig([{component: null, redirectTo: 'b'}]); }) expect(() => { validateConfig([{component: null, redirectTo: 'b'}] as any); })
.toThrowError( .toThrowError(
`Invalid configuration of route '': routes must have either a path or a matcher specified`); `Invalid configuration of route '': routes must have either a path or a matcher specified`);
}); });

View File

@ -19,7 +19,7 @@ describe('create router state', () => {
const reuseStrategy = new DefaultRouteReuseStrategy(); const reuseStrategy = new DefaultRouteReuseStrategy();
const emptyState = () => const emptyState = () =>
createEmptyState(new UrlTree(new UrlSegmentGroup([], {}), {}, null), RootComponent); createEmptyState(new UrlTree(new UrlSegmentGroup([], {}), {}, null !), RootComponent);
it('should work create new state', () => { it('should work create new state', () => {
const state = createRouterState( const state = createRouterState(
@ -76,8 +76,8 @@ describe('create router state', () => {
createRouterState(reuseStrategy, createState(config, 'a/2;p=22/(b//right:c)'), prevState); createRouterState(reuseStrategy, createState(config, 'a/2;p=22/(b//right:c)'), prevState);
expect(prevState.root).toBe(state.root); expect(prevState.root).toBe(state.root);
const prevP = prevState.firstChild(prevState.root); const prevP = prevState.firstChild(prevState.root) !;
const currP = state.firstChild(state.root); const currP = state.firstChild(state.root) !;
expect(prevP).toBe(currP); expect(prevP).toBe(currP);
const prevC = prevState.children(prevP); const prevC = prevState.children(prevP);
@ -101,7 +101,7 @@ function advanceNode(node: TreeNode<ActivatedRoute>): void {
} }
function createState(config: Routes, url: string): RouterStateSnapshot { function createState(config: Routes, url: string): RouterStateSnapshot {
let res: RouterStateSnapshot; let res: RouterStateSnapshot = undefined !;
recognize(RootComponent, config, tree(url), url).forEach(s => res = s); recognize(RootComponent, config, tree(url), url).forEach(s => res = s);
return res; return res;
} }

View File

@ -247,10 +247,10 @@ function createRoot(tree: UrlTree, commands: any[], queryParams?: Params, fragme
[], <any>{}, <any>{}, '', <any>{}, PRIMARY_OUTLET, 'someComponent', null, tree.root, -1, [], <any>{}, <any>{}, '', <any>{}, PRIMARY_OUTLET, 'someComponent', null, tree.root, -1,
<any>null); <any>null);
const a = new ActivatedRoute( const a = new ActivatedRoute(
new BehaviorSubject(null), new BehaviorSubject(null), new BehaviorSubject(null), new BehaviorSubject(null !), new BehaviorSubject(null !), new BehaviorSubject(null !),
new BehaviorSubject(null), new BehaviorSubject(null), PRIMARY_OUTLET, 'someComponent', s); new BehaviorSubject(null !), new BehaviorSubject(null !), PRIMARY_OUTLET, 'someComponent', s);
advanceActivatedRoute(a); advanceActivatedRoute(a);
return createUrlTree(a, tree, commands, queryParams, fragment); return createUrlTree(a, tree, commands, queryParams !, fragment !);
} }
function create( function create(
@ -263,8 +263,8 @@ function create(
[], <any>{}, <any>{}, '', <any>{}, PRIMARY_OUTLET, 'someComponent', null, <any>segment, [], <any>{}, <any>{}, '', <any>{}, PRIMARY_OUTLET, 'someComponent', null, <any>segment,
startIndex, <any>null); startIndex, <any>null);
const a = new ActivatedRoute( const a = new ActivatedRoute(
new BehaviorSubject(null), new BehaviorSubject(null), new BehaviorSubject(null), new BehaviorSubject(null !), new BehaviorSubject(null !), new BehaviorSubject(null !),
new BehaviorSubject(null), new BehaviorSubject(null), PRIMARY_OUTLET, 'someComponent', s); new BehaviorSubject(null !), new BehaviorSubject(null !), PRIMARY_OUTLET, 'someComponent', s);
advanceActivatedRoute(a); advanceActivatedRoute(a);
return createUrlTree(a, tree, commands, queryParams, fragment); return createUrlTree(a, tree, commands, queryParams !, fragment !);
} }

View File

@ -240,7 +240,7 @@ describe('Integration', () => {
advance(fixture); advance(fixture);
let recordedError: any = null; let recordedError: any = null;
router.navigateByUrl('/blank').catch(e => recordedError = e); router.navigateByUrl('/blank') !.catch(e => recordedError = e);
advance(fixture); advance(fixture);
expect(recordedError.message).toEqual('Cannot find primary outlet to load \'BlankCmp\''); expect(recordedError.message).toEqual('Cannot find primary outlet to load \'BlankCmp\'');
@ -620,8 +620,8 @@ describe('Integration', () => {
const user = fixture.debugElement.children[1].componentInstance; const user = fixture.debugElement.children[1].componentInstance;
let r1: any, r2: any; let r1: any, r2: any;
router.navigateByUrl('/user/victor').then(_ => r1 = _); router.navigateByUrl('/user/victor') !.then(_ => r1 = _);
router.navigateByUrl('/user/fedor').then(_ => r2 = _); router.navigateByUrl('/user/fedor') !.then(_ => r2 = _);
advance(fixture); advance(fixture);
expect(r1).toEqual(false); // returns false because it was canceled expect(r1).toEqual(false); // returns false because it was canceled
@ -650,7 +650,7 @@ describe('Integration', () => {
router.events.forEach(e => recordedEvents.push(e)); router.events.forEach(e => recordedEvents.push(e));
let e: any; let e: any;
router.navigateByUrl('/invalid').catch(_ => e = _); router.navigateByUrl('/invalid') !.catch(_ => e = _);
advance(fixture); advance(fixture);
expect(e.message).toContain('Cannot match any routes'); expect(e.message).toContain('Cannot match any routes');
@ -677,7 +677,7 @@ describe('Integration', () => {
router.events.forEach(e => recordedEvents.push(e)); router.events.forEach(e => recordedEvents.push(e));
let e: any; let e: any;
router.navigateByUrl('/invalid').then(_ => e = _); router.navigateByUrl('/invalid') !.then(_ => e = _);
advance(fixture); advance(fixture);
expect(e).toEqual('resolvedValue'); expect(e).toEqual('resolvedValue');
@ -911,7 +911,7 @@ describe('Integration', () => {
router.events.subscribe(e => recordedEvents.push(e)); router.events.subscribe(e => recordedEvents.push(e));
let e: any = null; let e: any = null;
router.navigateByUrl('/simple').catch(error => e = error); router.navigateByUrl('/simple') !.catch(error => e = error);
advance(fixture); advance(fixture);
expectEvents(recordedEvents, [ expectEvents(recordedEvents, [
@ -1688,7 +1688,7 @@ describe('Integration', () => {
{ {
provide: 'RecordingDeactivate', provide: 'RecordingDeactivate',
useValue: (c: any, a: ActivatedRouteSnapshot, b: RouterStateSnapshot) => { useValue: (c: any, a: ActivatedRouteSnapshot, b: RouterStateSnapshot) => {
log.push({path: a.routeConfig.path, component: c}); log.push({path: a.routeConfig !.path, component: c});
return true; return true;
} }
}, },
@ -1736,14 +1736,14 @@ describe('Integration', () => {
advance(fixture); advance(fixture);
expect(location.path()).toEqual('/team/22'); expect(location.path()).toEqual('/team/22');
let successStatus: boolean; let successStatus: boolean = false;
router.navigateByUrl('/team/33').then(res => successStatus = res); router.navigateByUrl('/team/33') !.then(res => successStatus = res);
advance(fixture); advance(fixture);
expect(location.path()).toEqual('/team/33'); expect(location.path()).toEqual('/team/33');
expect(successStatus).toEqual(true); expect(successStatus).toEqual(true);
let canceledStatus: boolean; let canceledStatus: boolean = false;
router.navigateByUrl('/team/44').then(res => canceledStatus = res); router.navigateByUrl('/team/44') !.then(res => canceledStatus = res);
advance(fixture); advance(fixture);
expect(location.path()).toEqual('/team/33'); expect(location.path()).toEqual('/team/33');
expect(canceledStatus).toEqual(false); expect(canceledStatus).toEqual(false);
@ -2073,7 +2073,7 @@ describe('Integration', () => {
expect(location.path()).toEqual('/team/22'); expect(location.path()).toEqual('/team/22');
router.navigateByUrl('/team/33').catch(() => {}); router.navigateByUrl('/team/33') !.catch(() => {});
advance(fixture); advance(fixture);
expect(location.path()).toEqual('/team/22'); expect(location.path()).toEqual('/team/22');
@ -2582,8 +2582,8 @@ describe('Integration', () => {
expect(location.path()).toEqual('/lazy/parent/child'); expect(location.path()).toEqual('/lazy/parent/child');
expect(fixture.nativeElement).toHaveText('parent[child]'); expect(fixture.nativeElement).toHaveText('parent[child]');
const pInj = fixture.debugElement.query(By.directive(Parent)).injector; const pInj = fixture.debugElement.query(By.directive(Parent)).injector !;
const cInj = fixture.debugElement.query(By.directive(Child)).injector; const cInj = fixture.debugElement.query(By.directive(Child)).injector !;
expect(pInj.get('moduleName')).toEqual('parent'); expect(pInj.get('moduleName')).toEqual('parent');
expect(pInj.get('fromParent')).toEqual('from parent'); expect(pInj.get('fromParent')).toEqual('from parent');
@ -2769,7 +2769,7 @@ describe('Integration', () => {
router.resetConfig([{path: 'lazy', loadChildren: 'expected'}]); router.resetConfig([{path: 'lazy', loadChildren: 'expected'}]);
let recordedError: any = null; let recordedError: any = null;
router.navigateByUrl('/lazy/loaded').catch(err => recordedError = err); router.navigateByUrl('/lazy/loaded') !.catch(err => recordedError = err);
advance(fixture); advance(fixture);
expect(recordedError.message) expect(recordedError.message)
.toEqual( .toEqual(
@ -2942,7 +2942,7 @@ describe('Integration', () => {
const recordedEvents: any[] = []; const recordedEvents: any[] = [];
router.events.forEach(e => recordedEvents.push(e)); router.events.forEach(e => recordedEvents.push(e));
router.navigateByUrl('/lazy/loaded').catch(s => {}); router.navigateByUrl('/lazy/loaded') !.catch(s => {});
advance(fixture); advance(fixture);
expect(location.path()).toEqual('/'); expect(location.path()).toEqual('/');
@ -3206,19 +3206,19 @@ describe('Integration', () => {
stored: {[k: string]: DetachedRouteHandle} = {}; stored: {[k: string]: DetachedRouteHandle} = {};
shouldDetach(route: ActivatedRouteSnapshot): boolean { shouldDetach(route: ActivatedRouteSnapshot): boolean {
return route.routeConfig.path === 'a'; return route.routeConfig !.path === 'a';
} }
store(route: ActivatedRouteSnapshot, detachedTree: DetachedRouteHandle): void { store(route: ActivatedRouteSnapshot, detachedTree: DetachedRouteHandle): void {
this.stored[route.routeConfig.path] = detachedTree; this.stored[route.routeConfig !.path !] = detachedTree;
} }
shouldAttach(route: ActivatedRouteSnapshot): boolean { shouldAttach(route: ActivatedRouteSnapshot): boolean {
return !!this.stored[route.routeConfig.path]; return !!this.stored[route.routeConfig !.path !];
} }
retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle { retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle {
return this.stored[route.routeConfig.path]; return this.stored[route.routeConfig !.path !];
} }
shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean { shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
@ -3230,7 +3230,7 @@ describe('Integration', () => {
shouldDetach(route: ActivatedRouteSnapshot): boolean { return false; } shouldDetach(route: ActivatedRouteSnapshot): boolean { return false; }
store(route: ActivatedRouteSnapshot, detachedTree: DetachedRouteHandle): void {} store(route: ActivatedRouteSnapshot, detachedTree: DetachedRouteHandle): void {}
shouldAttach(route: ActivatedRouteSnapshot): boolean { return false; } shouldAttach(route: ActivatedRouteSnapshot): boolean { return false; }
retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle { return null; } retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle { return null !; }
shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean { shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
if (future.routeConfig !== curr.routeConfig) { if (future.routeConfig !== curr.routeConfig) {
return false; return false;

View File

@ -16,14 +16,14 @@ describe('recognize', () => {
it('should work', () => { it('should work', () => {
checkRecognize([{path: 'a', component: ComponentA}], 'a', (s: RouterStateSnapshot) => { checkRecognize([{path: 'a', component: ComponentA}], 'a', (s: RouterStateSnapshot) => {
checkActivatedRoute(s.root, '', {}, RootComponent); checkActivatedRoute(s.root, '', {}, RootComponent);
checkActivatedRoute(s.firstChild(s.root), 'a', {}, ComponentA); checkActivatedRoute(s.firstChild(s.root) !, 'a', {}, ComponentA);
}); });
}); });
it('should freeze params object', () => { it('should freeze params object', () => {
checkRecognize([{path: 'a/:id', component: ComponentA}], 'a/10', (s: RouterStateSnapshot) => { checkRecognize([{path: 'a/:id', component: ComponentA}], 'a/10', (s: RouterStateSnapshot) => {
checkActivatedRoute(s.root, '', {}, RootComponent); checkActivatedRoute(s.root, '', {}, RootComponent);
const child = s.firstChild(s.root); const child = s.firstChild(s.root) !;
expect(Object.isFrozen(child.params)).toBeTruthy(); expect(Object.isFrozen(child.params)).toBeTruthy();
}); });
}); });
@ -79,11 +79,11 @@ describe('recognize', () => {
expect(s.root._urlSegment).toBe(url.root); expect(s.root._urlSegment).toBe(url.root);
expect(s.root._lastPathIndex).toBe(-1); expect(s.root._lastPathIndex).toBe(-1);
const compA = s.firstChild(s.root); const compA = s.firstChild(s.root) !;
expect(compA._urlSegment).toBe(url.root.children[PRIMARY_OUTLET]); expect(compA._urlSegment).toBe(url.root.children[PRIMARY_OUTLET]);
expect(compA._lastPathIndex).toBe(1); expect(compA._lastPathIndex).toBe(1);
const compC = s.firstChild(<any>compA); const compC = s.firstChild(<any>compA) !;
expect(compC._urlSegment).toBe(url.root.children[PRIMARY_OUTLET]); expect(compC._urlSegment).toBe(url.root.children[PRIMARY_OUTLET]);
expect(compC._lastPathIndex).toBe(2); expect(compC._lastPathIndex).toBe(2);
}); });
@ -101,11 +101,11 @@ describe('recognize', () => {
expect(s.root._urlSegment).toBe(url.root); expect(s.root._urlSegment).toBe(url.root);
expect(s.root._lastPathIndex).toBe(-1); expect(s.root._lastPathIndex).toBe(-1);
const compA = s.firstChild(s.root); const compA = s.firstChild(s.root) !;
expect(compA._urlSegment).toBe(url.root.children[PRIMARY_OUTLET]); expect(compA._urlSegment).toBe(url.root.children[PRIMARY_OUTLET]);
expect(compA._lastPathIndex).toBe(0); expect(compA._lastPathIndex).toBe(0);
const compC = s.firstChild(<any>compA); const compC = s.firstChild(<any>compA) !;
expect(compC._urlSegment).toBe(url.root.children[PRIMARY_OUTLET]); expect(compC._urlSegment).toBe(url.root.children[PRIMARY_OUTLET]);
expect(compC._lastPathIndex).toBe(2); expect(compC._lastPathIndex).toBe(2);
}); });
@ -119,16 +119,16 @@ describe('recognize', () => {
], ],
'a/paramA', (s: RouterStateSnapshot) => { 'a/paramA', (s: RouterStateSnapshot) => {
checkActivatedRoute(s.root, '', {}, RootComponent); checkActivatedRoute(s.root, '', {}, RootComponent);
checkActivatedRoute(s.firstChild(s.root), 'a', {}, ComponentA); checkActivatedRoute(s.firstChild(s.root) !, 'a', {}, ComponentA);
checkActivatedRoute( checkActivatedRoute(
s.firstChild(<any>s.firstChild(s.root)), 'paramA', {id: 'paramA'}, ComponentB); s.firstChild(<any>s.firstChild(s.root)) !, 'paramA', {id: 'paramA'}, ComponentB);
}); });
checkRecognize( checkRecognize(
[{path: 'a', component: ComponentA}, {path: 'a/:id', component: ComponentC}], 'a/paramA', [{path: 'a', component: ComponentA}, {path: 'a/:id', component: ComponentC}], 'a/paramA',
(s: RouterStateSnapshot) => { (s: RouterStateSnapshot) => {
checkActivatedRoute(s.root, '', {}, RootComponent); checkActivatedRoute(s.root, '', {}, RootComponent);
checkActivatedRoute(s.firstChild(s.root), 'a/paramA', {id: 'paramA'}, ComponentC); checkActivatedRoute(s.firstChild(s.root) !, 'a/paramA', {id: 'paramA'}, ComponentC);
}); });
}); });
@ -187,7 +187,7 @@ describe('recognize', () => {
'a;a1=11;a2=22/b;b1=111;b2=222(left:c;c1=1111;c2=2222)', (s: RouterStateSnapshot) => { 'a;a1=11;a2=22/b;b1=111;b2=222(left:c;c1=1111;c2=2222)', (s: RouterStateSnapshot) => {
const c = s.children(s.root); const c = s.children(s.root);
checkActivatedRoute(c[0], 'a', {a1: '11', a2: '22'}, ComponentA); checkActivatedRoute(c[0], 'a', {a1: '11', a2: '22'}, ComponentA);
checkActivatedRoute(s.firstChild(<any>c[0]), 'b', {b1: '111', b2: '222'}, ComponentB); checkActivatedRoute(s.firstChild(<any>c[0]) !, 'b', {b1: '111', b2: '222'}, ComponentB);
checkActivatedRoute(c[1], 'c', {c1: '1111', c2: '2222'}, ComponentC, 'left'); checkActivatedRoute(c[1], 'c', {c1: '1111', c2: '2222'}, ComponentC, 'left');
}); });
}); });
@ -196,7 +196,7 @@ describe('recognize', () => {
it('should set static data', () => { it('should set static data', () => {
checkRecognize( checkRecognize(
[{path: 'a', data: {one: 1}, component: ComponentA}], 'a', (s: RouterStateSnapshot) => { [{path: 'a', data: {one: 1}, component: ComponentA}], 'a', (s: RouterStateSnapshot) => {
const r: ActivatedRouteSnapshot = s.firstChild(s.root); const r: ActivatedRouteSnapshot = s.firstChild(s.root) !;
expect(r.data).toEqual({one: 1}); expect(r.data).toEqual({one: 1});
}); });
}); });
@ -209,7 +209,7 @@ describe('recognize', () => {
children: [{path: 'b', data: {two: 2}, component: ComponentB}] children: [{path: 'b', data: {two: 2}, component: ComponentB}]
}], }],
'a/b', (s: RouterStateSnapshot) => { 'a/b', (s: RouterStateSnapshot) => {
const r: ActivatedRouteSnapshot = s.firstChild(<any>s.firstChild(s.root)); const r: ActivatedRouteSnapshot = s.firstChild(<any>s.firstChild(s.root)) !;
expect(r.data).toEqual({one: 1, two: 2}); expect(r.data).toEqual({one: 1, two: 2});
}); });
}); });
@ -218,7 +218,7 @@ describe('recognize', () => {
checkRecognize( checkRecognize(
[{path: 'a', resolve: {one: 'some-token'}, component: ComponentA}], 'a', [{path: 'a', resolve: {one: 'some-token'}, component: ComponentA}], 'a',
(s: RouterStateSnapshot) => { (s: RouterStateSnapshot) => {
const r: ActivatedRouteSnapshot = s.firstChild(s.root); const r: ActivatedRouteSnapshot = s.firstChild(s.root) !;
expect(r._resolve).toEqual({one: 'some-token'}); expect(r._resolve).toEqual({one: 'some-token'});
}); });
}); });
@ -228,7 +228,7 @@ describe('recognize', () => {
describe('root', () => { describe('root', () => {
it('should work', () => { it('should work', () => {
checkRecognize([{path: '', component: ComponentA}], '', (s: RouterStateSnapshot) => { checkRecognize([{path: '', component: ComponentA}], '', (s: RouterStateSnapshot) => {
checkActivatedRoute(s.firstChild(s.root), '', {}, ComponentA); checkActivatedRoute(s.firstChild(s.root) !, '', {}, ComponentA);
}); });
}); });
@ -236,7 +236,7 @@ describe('recognize', () => {
checkRecognize( checkRecognize(
[{path: '', pathMatch: 'full', component: ComponentA}], '', [{path: '', pathMatch: 'full', component: ComponentA}], '',
(s: RouterStateSnapshot) => { (s: RouterStateSnapshot) => {
checkActivatedRoute(s.firstChild(s.root), '', {}, ComponentA); checkActivatedRoute(s.firstChild(s.root) !, '', {}, ComponentA);
}); });
}); });
@ -244,8 +244,8 @@ describe('recognize', () => {
checkRecognize( checkRecognize(
[{path: '', component: ComponentA, children: [{path: '', component: ComponentB}]}], '', [{path: '', component: ComponentA, children: [{path: '', component: ComponentB}]}], '',
(s: RouterStateSnapshot) => { (s: RouterStateSnapshot) => {
checkActivatedRoute(s.firstChild(s.root), '', {}, ComponentA); checkActivatedRoute(s.firstChild(s.root) !, '', {}, ComponentA);
checkActivatedRoute(s.firstChild(<any>s.firstChild(s.root)), '', {}, ComponentB); checkActivatedRoute(s.firstChild(<any>s.firstChild(s.root)) !, '', {}, ComponentB);
}); });
}); });
@ -259,11 +259,11 @@ describe('recognize', () => {
expect(s.root._urlSegment).toBe(url.root); expect(s.root._urlSegment).toBe(url.root);
expect(s.root._lastPathIndex).toBe(-1); expect(s.root._lastPathIndex).toBe(-1);
const c = s.firstChild(s.root); const c = s.firstChild(s.root) !;
expect(c._urlSegment).toBe(url.root); expect(c._urlSegment).toBe(url.root);
expect(c._lastPathIndex).toBe(-1); expect(c._lastPathIndex).toBe(-1);
const c2 = s.firstChild(<any>s.firstChild(s.root)); const c2 = s.firstChild(<any>s.firstChild(s.root)) !;
expect(c2._urlSegment).toBe(url.root); expect(c2._urlSegment).toBe(url.root);
expect(c2._lastPathIndex).toBe(-1); expect(c2._lastPathIndex).toBe(-1);
}); });
@ -279,10 +279,10 @@ describe('recognize', () => {
] ]
}], }],
'/a;p=1', (s: RouterStateSnapshot) => { '/a;p=1', (s: RouterStateSnapshot) => {
checkActivatedRoute(s.firstChild(s.root), 'a', {p: '1'}, ComponentA); checkActivatedRoute(s.firstChild(s.root) !, 'a', {p: '1'}, ComponentA);
checkActivatedRoute(s.firstChild(s.firstChild(s.root)), '', {p: '1'}, ComponentB); checkActivatedRoute(s.firstChild(s.firstChild(s.root) !) !, '', {p: '1'}, ComponentB);
checkActivatedRoute( checkActivatedRoute(
s.firstChild(s.firstChild(s.firstChild(s.root))), '', {p: '1'}, ComponentC); s.firstChild(s.firstChild(s.firstChild(s.root) !) !) !, '', {p: '1'}, ComponentC);
}); });
}); });
}); });
@ -299,9 +299,9 @@ describe('recognize', () => {
] ]
}], }],
'a/b', (s: RouterStateSnapshot) => { 'a/b', (s: RouterStateSnapshot) => {
checkActivatedRoute(s.firstChild(s.root), 'a', {}, ComponentA); checkActivatedRoute(s.firstChild(s.root) !, 'a', {}, ComponentA);
const c = s.children(s.firstChild(s.root)); const c = s.children(s.firstChild(s.root) !);
checkActivatedRoute(c[0], 'b', {}, ComponentB); checkActivatedRoute(c[0], 'b', {}, ComponentB);
checkActivatedRoute(c[1], '', {}, ComponentC, 'aux'); checkActivatedRoute(c[1], '', {}, ComponentC, 'aux');
}); });
@ -330,13 +330,13 @@ describe('recognize', () => {
checkRecognize(config, 'parent/b', (s: RouterStateSnapshot) => { checkRecognize(config, 'parent/b', (s: RouterStateSnapshot) => {
checkActivatedRoute(s.root, '', {}, RootComponent); checkActivatedRoute(s.root, '', {}, RootComponent);
checkActivatedRoute(s.firstChild(s.root), 'parent', {}, undefined); checkActivatedRoute(s.firstChild(s.root) !, 'parent', {}, undefined !);
const cc = s.children(s.firstChild(s.root)); const cc = s.children(s.firstChild(s.root) !);
checkActivatedRoute(cc[0], '', {}, ComponentA); checkActivatedRoute(cc[0], '', {}, ComponentA);
checkActivatedRoute(cc[1], '', {}, ComponentD, 'secondary'); checkActivatedRoute(cc[1], '', {}, ComponentD, 'secondary');
checkActivatedRoute(s.firstChild(cc[0]), 'b', {}, ComponentB); checkActivatedRoute(s.firstChild(cc[0]) !, 'b', {}, ComponentB);
}); });
}); });
@ -351,9 +351,9 @@ describe('recognize', () => {
] ]
}], }],
'a/b', (s: RouterStateSnapshot) => { 'a/b', (s: RouterStateSnapshot) => {
checkActivatedRoute(s.firstChild(s.root), 'a', {}, ComponentA); checkActivatedRoute(s.firstChild(s.root) !, 'a', {}, ComponentA);
const c = s.children(s.firstChild(s.root)); const c = s.children(s.firstChild(s.root) !);
expect(c.length).toEqual(1); expect(c.length).toEqual(1);
checkActivatedRoute(c[0], 'b', {}, ComponentB); checkActivatedRoute(c[0], 'b', {}, ComponentB);
}); });
@ -375,11 +375,11 @@ describe('recognize', () => {
expect(s.root._urlSegment).toBe(url.root); expect(s.root._urlSegment).toBe(url.root);
expect(s.root._lastPathIndex).toBe(-1); expect(s.root._lastPathIndex).toBe(-1);
const a = s.firstChild(s.root); const a = s.firstChild(s.root) !;
expect(a._urlSegment).toBe(url.root.children[PRIMARY_OUTLET]); expect(a._urlSegment).toBe(url.root.children[PRIMARY_OUTLET]);
expect(a._lastPathIndex).toBe(0); expect(a._lastPathIndex).toBe(0);
const b = s.firstChild(a); const b = s.firstChild(a) !;
expect(b._urlSegment).toBe(url.root.children[PRIMARY_OUTLET]); expect(b._urlSegment).toBe(url.root.children[PRIMARY_OUTLET]);
expect(b._lastPathIndex).toBe(1); expect(b._lastPathIndex).toBe(1);
@ -403,15 +403,15 @@ describe('recognize', () => {
expect(s.root._urlSegment).toBe(url.root); expect(s.root._urlSegment).toBe(url.root);
expect(s.root._lastPathIndex).toBe(-1); expect(s.root._lastPathIndex).toBe(-1);
const a = s.firstChild(s.root); const a = s.firstChild(s.root) !;
expect(a._urlSegment).toBe(url.root.children[PRIMARY_OUTLET]); expect(a._urlSegment).toBe(url.root.children[PRIMARY_OUTLET]);
expect(a._lastPathIndex).toBe(0); expect(a._lastPathIndex).toBe(0);
const b = s.firstChild(a); const b = s.firstChild(a) !;
expect(b._urlSegment).toBe(url.root.children[PRIMARY_OUTLET]); expect(b._urlSegment).toBe(url.root.children[PRIMARY_OUTLET]);
expect(b._lastPathIndex).toBe(0); expect(b._lastPathIndex).toBe(0);
const c = s.firstChild(b); const c = s.firstChild(b) !;
expect(c._urlSegment).toBe(url.root.children[PRIMARY_OUTLET]); expect(c._urlSegment).toBe(url.root.children[PRIMARY_OUTLET]);
expect(c._lastPathIndex).toBe(0); expect(c._lastPathIndex).toBe(0);
}); });
@ -431,15 +431,15 @@ describe('recognize', () => {
expect(s.root._urlSegment).toBe(url.root); expect(s.root._urlSegment).toBe(url.root);
expect(s.root._lastPathIndex).toBe(-1); expect(s.root._lastPathIndex).toBe(-1);
const a = s.firstChild(s.root); const a = s.firstChild(s.root) !;
expect(a._urlSegment).toBe(url.root); expect(a._urlSegment).toBe(url.root);
expect(a._lastPathIndex).toBe(-1); expect(a._lastPathIndex).toBe(-1);
const b = s.firstChild(a); const b = s.firstChild(a) !;
expect(b._urlSegment).toBe(url.root); expect(b._urlSegment).toBe(url.root);
expect(b._lastPathIndex).toBe(-1); expect(b._lastPathIndex).toBe(-1);
const c = s.firstChild(b); const c = s.firstChild(b) !;
expect(c._urlSegment).toBe(url.root); expect(c._urlSegment).toBe(url.root);
expect(c._lastPathIndex).toBe(-1); expect(c._lastPathIndex).toBe(-1);
}); });
@ -458,9 +458,9 @@ describe('recognize', () => {
] ]
}], }],
'a', (s: RouterStateSnapshot) => { 'a', (s: RouterStateSnapshot) => {
checkActivatedRoute(s.firstChild(s.root), 'a', {}, ComponentA); checkActivatedRoute(s.firstChild(s.root) !, 'a', {}, ComponentA);
const c = s.children(s.firstChild(s.root)); const c = s.children(s.firstChild(s.root) !);
checkActivatedRoute(c[0], '', {}, ComponentB); checkActivatedRoute(c[0], '', {}, ComponentB);
checkActivatedRoute(c[1], '', {}, ComponentC, 'aux'); checkActivatedRoute(c[1], '', {}, ComponentC, 'aux');
}); });
@ -477,9 +477,9 @@ describe('recognize', () => {
] ]
}], }],
'a', (s: RouterStateSnapshot) => { 'a', (s: RouterStateSnapshot) => {
checkActivatedRoute(s.firstChild(s.root), 'a', {}, ComponentA); checkActivatedRoute(s.firstChild(s.root) !, 'a', {}, ComponentA);
const c = s.children(s.firstChild(s.root)); const c = s.children(s.firstChild(s.root) !);
checkActivatedRoute(c[0], '', {}, ComponentB); checkActivatedRoute(c[0], '', {}, ComponentB);
checkActivatedRoute(c[1], '', {}, ComponentC, 'aux'); checkActivatedRoute(c[1], '', {}, ComponentC, 'aux');
}); });
@ -496,9 +496,9 @@ describe('recognize', () => {
] ]
}], }],
'a/(aux:c)', (s: RouterStateSnapshot) => { 'a/(aux:c)', (s: RouterStateSnapshot) => {
checkActivatedRoute(s.firstChild(s.root), 'a', {}, ComponentA); checkActivatedRoute(s.firstChild(s.root) !, 'a', {}, ComponentA);
const c = s.children(s.firstChild(s.root)); const c = s.children(s.firstChild(s.root) !);
checkActivatedRoute(c[0], '', {}, ComponentB); checkActivatedRoute(c[0], '', {}, ComponentB);
checkActivatedRoute(c[1], 'c', {}, ComponentC, 'aux'); checkActivatedRoute(c[1], 'c', {}, ComponentC, 'aux');
}); });
@ -538,13 +538,13 @@ describe('recognize', () => {
] ]
}], }],
'a/(d//aux:e)', (s: RouterStateSnapshot) => { 'a/(d//aux:e)', (s: RouterStateSnapshot) => {
checkActivatedRoute(s.firstChild(s.root), 'a', {}, ComponentA); checkActivatedRoute(s.firstChild(s.root) !, 'a', {}, ComponentA);
const c = s.children(s.firstChild(s.root)); const c = s.children(s.firstChild(s.root) !);
checkActivatedRoute(c[0], '', {}, ComponentB); checkActivatedRoute(c[0], '', {}, ComponentB);
checkActivatedRoute(s.firstChild(c[0]), 'd', {}, ComponentD); checkActivatedRoute(s.firstChild(c[0]) !, 'd', {}, ComponentD);
checkActivatedRoute(c[1], '', {}, ComponentC, 'aux'); checkActivatedRoute(c[1], '', {}, ComponentC, 'aux');
checkActivatedRoute(s.firstChild(c[1]), 'e', {}, ComponentE); checkActivatedRoute(s.firstChild(c[1]) !, 'e', {}, ComponentE);
}); });
}); });
}); });
@ -554,7 +554,7 @@ describe('recognize', () => {
it('should support simple wildcards', () => { it('should support simple wildcards', () => {
checkRecognize( checkRecognize(
[{path: '**', component: ComponentA}], 'a/b/c/d;a1=11', (s: RouterStateSnapshot) => { [{path: '**', component: ComponentA}], 'a/b/c/d;a1=11', (s: RouterStateSnapshot) => {
checkActivatedRoute(s.firstChild(s.root), 'a/b/c/d', {a1: '11'}, ComponentA); checkActivatedRoute(s.firstChild(s.root) !, 'a/b/c/d', {a1: '11'}, ComponentA);
}); });
}); });
}); });
@ -570,8 +570,8 @@ describe('recognize', () => {
] ]
}], }],
'p/11;pp=22/(a;pa=33//aux:b;pb=44)', (s: RouterStateSnapshot) => { 'p/11;pp=22/(a;pa=33//aux:b;pb=44)', (s: RouterStateSnapshot) => {
const p = s.firstChild(s.root); const p = s.firstChild(s.root) !;
checkActivatedRoute(p, 'p/11', {id: '11', pp: '22'}, undefined); checkActivatedRoute(p, 'p/11', {id: '11', pp: '22'}, undefined !);
const c = s.children(p); const c = s.children(p);
checkActivatedRoute(c[0], 'a', {id: '11', pp: '22', pa: '33'}, ComponentA); checkActivatedRoute(c[0], 'a', {id: '11', pp: '22', pa: '33'}, ComponentA);
@ -593,16 +593,16 @@ describe('recognize', () => {
}] }]
}], }],
'p/11/a/victor/b/c', (s: RouterStateSnapshot) => { 'p/11/a/victor/b/c', (s: RouterStateSnapshot) => {
const p = s.firstChild(s.root); const p = s.firstChild(s.root) !;
checkActivatedRoute(p, 'p/11', {id: '11'}, undefined); checkActivatedRoute(p, 'p/11', {id: '11'}, undefined !);
const a = s.firstChild(p); const a = s.firstChild(p) !;
checkActivatedRoute(a, 'a/victor', {id: '11', name: 'victor'}, undefined); checkActivatedRoute(a, 'a/victor', {id: '11', name: 'victor'}, undefined !);
const b = s.firstChild(a); const b = s.firstChild(a) !;
checkActivatedRoute(b, 'b', {id: '11', name: 'victor'}, ComponentB); checkActivatedRoute(b, 'b', {id: '11', name: 'victor'}, ComponentB);
const c = s.firstChild(b); const c = s.firstChild(b) !;
checkActivatedRoute(c, 'c', {}, ComponentC); checkActivatedRoute(c, 'c', {}, ComponentC);
}); });
}); });
@ -614,7 +614,7 @@ describe('recognize', () => {
[{path: 'a', component: ComponentA, children: [{path: 'b', component: ComponentB}]}], [{path: 'a', component: ComponentA, children: [{path: 'b', component: ComponentB}]}],
'/a', (s: RouterStateSnapshot) => { '/a', (s: RouterStateSnapshot) => {
const a = s.firstChild(s.root); const a = s.firstChild(s.root);
checkActivatedRoute(a, 'a', {}, ComponentA); checkActivatedRoute(a !, 'a', {}, ComponentA);
}); });
}); });
@ -629,7 +629,7 @@ describe('recognize', () => {
] ]
}], }],
'/a', (s: RouterStateSnapshot) => { '/a', (s: RouterStateSnapshot) => {
const a = s.firstChild(s.root); const a = s.firstChild(s.root) !;
checkActivatedRoute(a, 'a', {}, ComponentA); checkActivatedRoute(a, 'a', {}, ComponentA);
checkActivatedRoute(a.children[0], '', {}, ComponentC, 'aux'); checkActivatedRoute(a.children[0], '', {}, ComponentC, 'aux');
}); });
@ -651,11 +651,11 @@ describe('recognize', () => {
matcher: matcher, matcher: matcher,
component: ComponentA, component: ComponentA,
children: [{path: 'b', component: ComponentB}] children: [{path: 'b', component: ComponentB}]
}], }] as any,
'/a/1;p=99/b', (s: RouterStateSnapshot) => { '/a/1;p=99/b', (s: RouterStateSnapshot) => {
const a = s.root.firstChild; const a = s.root.firstChild !;
checkActivatedRoute(a, 'a/1', {id: '1', p: '99'}, ComponentA); checkActivatedRoute(a, 'a/1', {id: '1', p: '99'}, ComponentA);
checkActivatedRoute(a.firstChild, 'b', {}, ComponentB); checkActivatedRoute(a.firstChild !, 'b', {}, ComponentB);
}); });
}); });
}); });

View File

@ -57,7 +57,7 @@ describe('Router', () => {
const inj = {get: (token: any) => () => `${token}_value`}; const inj = {get: (token: any) => () => `${token}_value`};
let empty: RouterStateSnapshot; let empty: RouterStateSnapshot;
beforeEach(() => { empty = createEmptyStateSnapshot(serializer.parse('/'), null); }); beforeEach(() => { empty = createEmptyStateSnapshot(serializer.parse('/'), null !); });
it('should resolve data', () => { it('should resolve data', () => {
const r = {data: 'resolver'}; const r = {data: 'resolver'};
@ -65,7 +65,7 @@ describe('Router', () => {
const s = new RouterStateSnapshot('url', new TreeNode(empty.root, [new TreeNode(n, [])])); const s = new RouterStateSnapshot('url', new TreeNode(empty.root, [new TreeNode(n, [])]));
checkResolveData(s, empty, inj, () => { checkResolveData(s, empty, inj, () => {
expect(s.root.firstChild.data).toEqual({data: 'resolver_value'}); expect(s.root.firstChild !.data).toEqual({data: 'resolver_value'});
}); });
}); });
@ -73,7 +73,7 @@ describe('Router', () => {
const parentResolve = {data: 'resolver'}; const parentResolve = {data: 'resolver'};
const childResolve = {}; const childResolve = {};
const parent = createActivatedRouteSnapshot(null, {resolve: parentResolve}); const parent = createActivatedRouteSnapshot(null !, {resolve: parentResolve});
const child = createActivatedRouteSnapshot('b', {resolve: childResolve}); const child = createActivatedRouteSnapshot('b', {resolve: childResolve});
const s = new RouterStateSnapshot( const s = new RouterStateSnapshot(
@ -82,7 +82,7 @@ describe('Router', () => {
const inj = {get: (token: any) => () => Promise.resolve(`${token}_value`)}; const inj = {get: (token: any) => () => Promise.resolve(`${token}_value`)};
checkResolveData(s, empty, inj, () => { checkResolveData(s, empty, inj, () => {
expect(s.root.firstChild.firstChild.data).toEqual({data: 'resolver_value'}); expect(s.root.firstChild !.firstChild !.data).toEqual({data: 'resolver_value'});
}); });
}); });
@ -99,8 +99,8 @@ describe('Router', () => {
const s2 = new RouterStateSnapshot( const s2 = new RouterStateSnapshot(
'url', new TreeNode(empty.root, [new TreeNode(n21, [new TreeNode(n22, [])])])); 'url', new TreeNode(empty.root, [new TreeNode(n21, [new TreeNode(n22, [])])]));
checkResolveData(s2, s1, inj, () => { checkResolveData(s2, s1, inj, () => {
expect(s2.root.firstChild.data).toEqual({data: 'resolver1_value'}); expect(s2.root.firstChild !.data).toEqual({data: 'resolver1_value'});
expect(s2.root.firstChild.firstChild.data).toEqual({data: 'resolver2_value'}); expect(s2.root.firstChild !.firstChild !.data).toEqual({data: 'resolver2_value'});
}); });
}); });
}); });

View File

@ -39,17 +39,17 @@ describe('RouterState & Snapshot', () => {
}); });
it('should return root', () => { it('should return root', () => {
const b = state.root.firstChild; const b = state.root.firstChild !;
expect(b.root).toBe(state.root); expect(b.root).toBe(state.root);
}); });
it('should return parent', () => { it('should return parent', () => {
const b = state.root.firstChild; const b = state.root.firstChild !;
expect(b.parent).toBe(state.root); expect(b.parent).toBe(state.root);
}); });
it('should return path from root', () => { it('should return path from root', () => {
const b = state.root.firstChild; const b = state.root.firstChild !;
const p = b.pathFromRoot; const p = b.pathFromRoot;
expect(p[0]).toBe(state.root); expect(p[0]).toBe(state.root);
expect(p[1]).toBe(b); expect(p[1]).toBe(b);
@ -81,17 +81,17 @@ describe('RouterState & Snapshot', () => {
}); });
it('should return root', () => { it('should return root', () => {
const b = state.root.firstChild; const b = state.root.firstChild !;
expect(b.root).toBe(state.root); expect(b.root).toBe(state.root);
}); });
it('should return parent', () => { it('should return parent', () => {
const b = state.root.firstChild; const b = state.root.firstChild !;
expect(b.parent).toBe(state.root); expect(b.parent).toBe(state.root);
}); });
it('should return path from root', () => { it('should return path from root', () => {
const b = state.root.firstChild; const b = state.root.firstChild !;
const p = b.pathFromRoot; const p = b.pathFromRoot;
expect(p[0]).toBe(state.root); expect(p[0]).toBe(state.root);
expect(p[1]).toBe(b); expect(p[1]).toBe(b);
@ -102,7 +102,7 @@ describe('RouterState & Snapshot', () => {
function createSnapshot(params: Params, url: UrlSegment[]): ActivatedRouteSnapshot { function createSnapshot(params: Params, url: UrlSegment[]): ActivatedRouteSnapshot {
const snapshot = new ActivatedRouteSnapshot( const snapshot = new ActivatedRouteSnapshot(
url, params, <any>null, <any>null, <any>null, <any>null, <any>null, <any>null, <any>null, url, params, <any>null, <any>null, <any>null, <any>null, <any>null, <any>null, <any>null,
-1, null); -1, null !);
snapshot._routerState = new RouterStateSnapshot('', new TreeNode(snapshot, [])); snapshot._routerState = new RouterStateSnapshot('', new TreeNode(snapshot, []));
return snapshot; return snapshot;
} }
@ -177,7 +177,7 @@ describe('RouterState & Snapshot', () => {
const data = {}; const data = {};
const snapshot = new ActivatedRouteSnapshot( const snapshot = new ActivatedRouteSnapshot(
url, params, queryParams, fragment, data, <any>null, <any>null, <any>null, <any>null, -1, url, params, queryParams, fragment, data, <any>null, <any>null, <any>null, <any>null, -1,
null); null !);
const state = new RouterStateSnapshot('', new TreeNode(snapshot, [])); const state = new RouterStateSnapshot('', new TreeNode(snapshot, []));
snapshot._routerState = state; snapshot._routerState = state;
return snapshot; return snapshot;
@ -200,7 +200,7 @@ describe('RouterState & Snapshot', () => {
function createActivatedRouteSnapshot(cmp: string) { function createActivatedRouteSnapshot(cmp: string) {
return new ActivatedRouteSnapshot( return new ActivatedRouteSnapshot(
<any>null, <any>null, <any>null, <any>null, <any>null, <any>null, <any>cmp, <any>null, <any>null, <any>null, <any>null, <any>null, <any>null, <any>null, <any>cmp, <any>null,
<any>null, -1, null); <any>null, -1, null !);
} }
function createActivatedRoute(cmp: string) { function createActivatedRoute(cmp: string) {

View File

@ -86,7 +86,7 @@ export function setupTestingRouter(
loader: NgModuleFactoryLoader, compiler: Compiler, injector: Injector, routes: Route[][], loader: NgModuleFactoryLoader, compiler: Compiler, injector: Injector, routes: Route[][],
urlHandlingStrategy?: UrlHandlingStrategy) { urlHandlingStrategy?: UrlHandlingStrategy) {
const router = new Router( const router = new Router(
null, urlSerializer, outletMap, location, injector, loader, compiler, flatten(routes)); null !, urlSerializer, outletMap, location, injector, loader, compiler, flatten(routes));
if (urlHandlingStrategy) { if (urlHandlingStrategy) {
router.urlHandlingStrategy = urlHandlingStrategy; router.urlHandlingStrategy = urlHandlingStrategy;
} }

View File

@ -10,6 +10,7 @@
"noEmitOnError": false, "noEmitOnError": false,
"noImplicitAny": true, "noImplicitAny": true,
"noImplicitReturns": true, "noImplicitReturns": true,
"strictNullChecks": true,
"outDir": "../../dist/packages/router", "outDir": "../../dist/packages/router",
"paths": { "paths": {
"@angular/core": ["../../dist/packages/core"], "@angular/core": ["../../dist/packages/core"],

View File

@ -1,19 +1,19 @@
/** @stable */ /** @stable */
export declare class ActivatedRoute { export declare class ActivatedRoute {
readonly children: ActivatedRoute[]; readonly children: ActivatedRoute[];
component: Type<any> | string; component: Type<any> | string | null;
data: Observable<Data>; data: Observable<Data>;
readonly firstChild: ActivatedRoute; readonly firstChild: ActivatedRoute | null;
fragment: Observable<string>; fragment: Observable<string>;
outlet: string; outlet: string;
readonly paramMap: Observable<ParamMap>; readonly paramMap: Observable<ParamMap>;
params: Observable<Params>; params: Observable<Params>;
readonly parent: ActivatedRoute; readonly parent: ActivatedRoute | null;
readonly pathFromRoot: ActivatedRoute[]; readonly pathFromRoot: ActivatedRoute[];
readonly queryParamMap: Observable<ParamMap>; readonly queryParamMap: Observable<ParamMap>;
queryParams: Observable<Params>; queryParams: Observable<Params>;
readonly root: ActivatedRoute; readonly root: ActivatedRoute;
readonly routeConfig: Route; readonly routeConfig: Route | null;
snapshot: ActivatedRouteSnapshot; snapshot: ActivatedRouteSnapshot;
url: Observable<UrlSegment[]>; url: Observable<UrlSegment[]>;
toString(): string; toString(): string;
@ -22,19 +22,19 @@ export declare class ActivatedRoute {
/** @stable */ /** @stable */
export declare class ActivatedRouteSnapshot { export declare class ActivatedRouteSnapshot {
readonly children: ActivatedRouteSnapshot[]; readonly children: ActivatedRouteSnapshot[];
component: Type<any> | string; component: Type<any> | string | null;
data: Data; data: Data;
readonly firstChild: ActivatedRouteSnapshot; readonly firstChild: ActivatedRouteSnapshot | null;
fragment: string; fragment: string;
outlet: string; outlet: string;
readonly paramMap: ParamMap; readonly paramMap: ParamMap;
params: Params; params: Params;
readonly parent: ActivatedRouteSnapshot; readonly parent: ActivatedRouteSnapshot | null;
readonly pathFromRoot: ActivatedRouteSnapshot[]; readonly pathFromRoot: ActivatedRouteSnapshot[];
readonly queryParamMap: ParamMap; readonly queryParamMap: ParamMap;
queryParams: Params; queryParams: Params;
readonly root: ActivatedRouteSnapshot; readonly root: ActivatedRouteSnapshot;
readonly routeConfig: Route; readonly routeConfig: Route | null;
url: UrlSegment[]; url: UrlSegment[];
toString(): string; toString(): string;
} }
@ -239,7 +239,7 @@ export declare class Router {
readonly routerState: RouterState; readonly routerState: RouterState;
readonly url: string; readonly url: string;
urlHandlingStrategy: UrlHandlingStrategy; urlHandlingStrategy: UrlHandlingStrategy;
constructor(rootComponentType: Type<any>, urlSerializer: UrlSerializer, outletMap: RouterOutletMap, location: Location, injector: Injector, loader: NgModuleFactoryLoader, compiler: Compiler, config: Routes); constructor(rootComponentType: Type<any> | null, urlSerializer: UrlSerializer, outletMap: RouterOutletMap, location: Location, injector: Injector, loader: NgModuleFactoryLoader, compiler: Compiler, config: Routes);
createUrlTree(commands: any[], {relativeTo, queryParams, fragment, preserveQueryParams, queryParamsHandling, preserveFragment}?: NavigationExtras): UrlTree; createUrlTree(commands: any[], {relativeTo, queryParams, fragment, preserveQueryParams, queryParamsHandling, preserveFragment}?: NavigationExtras): UrlTree;
dispose(): void; dispose(): void;
initialNavigation(): void; initialNavigation(): void;
@ -261,11 +261,11 @@ export declare const ROUTER_INITIALIZER: InjectionToken<(compRef: ComponentRef<a
/** @experimental */ /** @experimental */
export declare abstract class RouteReuseStrategy { export declare abstract class RouteReuseStrategy {
abstract retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle; abstract retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle | null;
abstract shouldAttach(route: ActivatedRouteSnapshot): boolean; abstract shouldAttach(route: ActivatedRouteSnapshot): boolean;
abstract shouldDetach(route: ActivatedRouteSnapshot): boolean; abstract shouldDetach(route: ActivatedRouteSnapshot): boolean;
abstract shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean; abstract shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean;
abstract store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): void; abstract store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle | null): void;
} }
/** @stable */ /** @stable */
@ -424,7 +424,7 @@ export declare class UrlSegmentGroup {
[key: string]: UrlSegmentGroup; [key: string]: UrlSegmentGroup;
}; };
readonly numberOfChildren: number; readonly numberOfChildren: number;
parent: UrlSegmentGroup; parent: UrlSegmentGroup | null;
segments: UrlSegment[]; segments: UrlSegment[];
constructor( constructor(
segments: UrlSegment[], segments: UrlSegment[],
@ -443,7 +443,7 @@ export declare abstract class UrlSerializer {
/** @stable */ /** @stable */
export declare class UrlTree { export declare class UrlTree {
fragment: string; fragment: string | null;
readonly queryParamMap: ParamMap; readonly queryParamMap: ParamMap;
queryParams: { queryParams: {
[key: string]: string; [key: string]: string;