From bc431888f32c4222d1e00c81668235d006b0792e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=A1ko=20Hevery?= Date: Mon, 17 Apr 2017 11:13:13 -0700 Subject: [PATCH] fix(router): Update types for TypeScript nullability support This reverts commit ea8ffc984136ef4d32b6858fe35e69cc9fced021. --- packages/router/src/apply_redirects.ts | 24 ++-- packages/router/src/create_url_tree.ts | 2 +- .../router/src/directives/router_outlet.ts | 16 +-- packages/router/src/recognize.ts | 20 +-- packages/router/src/route_reuse_strategy.ts | 4 +- packages/router/src/router.ts | 61 ++++----- packages/router/src/router_config_loader.ts | 2 +- packages/router/src/router_module.ts | 6 +- packages/router/src/router_outlet_map.ts | 2 +- packages/router/src/router_state.ts | 26 ++-- packages/router/src/shared.ts | 2 +- packages/router/src/url_tree.ts | 12 +- packages/router/src/utils/collection.ts | 2 +- packages/router/src/utils/tree.ts | 6 +- packages/router/test/apply_redirects.spec.ts | 14 +- packages/router/test/bootstrap.spec.ts | 4 +- packages/router/test/config.spec.ts | 7 +- .../router/test/create_router_state.spec.ts | 8 +- packages/router/test/create_url_tree.spec.ts | 12 +- packages/router/test/integration.spec.ts | 42 +++--- packages/router/test/recognize.spec.ts | 122 +++++++++--------- packages/router/test/router.spec.ts | 12 +- packages/router/test/router_state.spec.ts | 18 +-- .../testing/src/router_testing_module.ts | 2 +- packages/router/tsconfig-build.json | 1 + tools/public_api_guard/router/router.d.ts | 26 ++-- 26 files changed, 230 insertions(+), 223 deletions(-) diff --git a/packages/router/src/apply_redirects.ts b/packages/router/src/apply_redirects.ts index 0805761d1b..8af1df37c9 100644 --- a/packages/router/src/apply_redirects.ts +++ b/packages/router/src/apply_redirects.ts @@ -25,7 +25,9 @@ import {UrlSegment, UrlSegmentGroup, UrlSerializer, UrlTree} from './url_tree'; import {andObservables, forEach, waitForMap, wrapIntoObservable} from './utils/collection'; class NoMatch { - constructor(public segmentGroup: UrlSegmentGroup = null) {} + public segmentGroup: UrlSegmentGroup|null; + + constructor(segmentGroup?: UrlSegmentGroup) { this.segmentGroup = segmentGroup || null; } } class AbsoluteRedirect { @@ -80,7 +82,7 @@ class ApplyRedirects { this.expandSegmentGroup(this.ngModule, this.config, this.urlTree.root, PRIMARY_OUTLET); const urlTrees$ = map.call( 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) => { if (e instanceof AbsoluteRedirect) { // 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); const mapped$ = map.call( expanded$, (rootSegmentGroup: UrlSegmentGroup) => - this.createUrlTree(rootSegmentGroup, tree.queryParams, tree.fragment)); + this.createUrlTree(rootSegmentGroup, tree.queryParams, tree.fragment !)); return _catch.call(mapped$, (e: any): Observable => { if (e instanceof NoMatch) { throw this.noMatchError(e); @@ -215,8 +217,8 @@ class ApplyRedirects { private expandWildCardWithParamsAgainstRouteUsingRedirect( ngModule: NgModuleRef, routes: Route[], route: Route, outlet: string): Observable { - const newTree = this.applyRedirectCommands([], route.redirectTo, {}); - if (route.redirectTo.startsWith('/')) { + const newTree = this.applyRedirectCommands([], route.redirectTo !, {}); + if (route.redirectTo !.startsWith('/')) { return absoluteRedirect(newTree); } @@ -234,8 +236,8 @@ class ApplyRedirects { if (!matched) return noMatch(segmentGroup); const newTree = this.applyRedirectCommands( - consumedSegments, route.redirectTo, positionalParamSegments); - if (route.redirectTo.startsWith('/')) { + consumedSegments, route.redirectTo !, positionalParamSegments); + if (route.redirectTo !.startsWith('/')) { return absoluteRedirect(newTree); } @@ -331,7 +333,7 @@ class ApplyRedirects { } if (c.numberOfChildren > 1 || !c.children[PRIMARY_OUTLET]) { - return namedOutletsRedirect(route.redirectTo); + return namedOutletsRedirect(route.redirectTo !); } c = c.children[PRIMARY_OUTLET]; @@ -442,9 +444,9 @@ function match(segmentGroup: UrlSegmentGroup, route: Route, segments: UrlSegment return { matched: true, - consumedSegments: res.consumed, - lastChild: res.consumed.length, - positionalParamSegments: res.posParams, + consumedSegments: res.consumed !, + lastChild: res.consumed.length !, + positionalParamSegments: res.posParams !, }; } diff --git a/packages/router/src/create_url_tree.ts b/packages/router/src/create_url_tree.ts index ab0d3e6bb5..c454af5099 100644 --- a/packages/router/src/create_url_tree.ts +++ b/packages/router/src/create_url_tree.ts @@ -164,7 +164,7 @@ function createPositionApplyingDoubleDots( let dd = numberOfDoubleDots; while (dd > ci) { dd -= ci; - g = g.parent; + g = g.parent !; if (!g) { throw new Error('Invalid number of \'../\''); } diff --git a/packages/router/src/directives/router_outlet.ts b/packages/router/src/directives/router_outlet.ts index 435590b2e9..a6938e55e3 100644 --- a/packages/router/src/directives/router_outlet.ts +++ b/packages/router/src/directives/router_outlet.ts @@ -71,8 +71,8 @@ export class RouterOutlet implements OnDestroy { if (!this.activated) throw new Error('Outlet is not activated'); this.location.detach(); const r = this.activated; - this.activated = null; - this._activatedRoute = null; + this.activated = null !; + this._activatedRoute = null !; return r; } @@ -86,8 +86,8 @@ export class RouterOutlet implements OnDestroy { if (this.activated) { const c = this.component; this.activated.destroy(); - this.activated = null; - this._activatedRoute = null; + this.activated = null !; + this._activatedRoute = null !; this.deactivateEvents.emit(c); } } @@ -104,8 +104,8 @@ export class RouterOutlet implements OnDestroy { this._activatedRoute = activatedRoute; const snapshot = activatedRoute._futureSnapshot; - const component: any = snapshot._routeConfig.component; - const factory = resolver.resolveComponentFactory(component); + const component: any = snapshot._routeConfig !.component; + const factory = resolver.resolveComponentFactory(component) !; const inj = ReflectiveInjector.fromResolvedProviders(providers, injector); @@ -126,10 +126,10 @@ export class RouterOutlet implements OnDestroy { this._activatedRoute = activatedRoute; const snapshot = activatedRoute._futureSnapshot; - const component = snapshot._routeConfig.component; + const component = snapshot._routeConfig !.component; resolver = resolver || this.resolver; - const factory = resolver.resolveComponentFactory(component); + const factory = resolver.resolveComponentFactory(component) !; const injector = new OutletInjector(activatedRoute, outletMap, this.location.injector); diff --git a/packages/router/src/recognize.ts b/packages/router/src/recognize.ts index 684e2c6a1b..09ed8453b1 100644 --- a/packages/router/src/recognize.ts +++ b/packages/router/src/recognize.ts @@ -21,14 +21,14 @@ import {TreeNode} from './utils/tree'; class NoMatch {} export function recognize( - rootComponentType: Type, config: Routes, urlTree: UrlTree, + rootComponentType: Type| null, config: Routes, urlTree: UrlTree, url: string): Observable { return new Recognizer(rootComponentType, config, urlTree, url).recognize(); } class Recognizer { constructor( - private rootComponentType: Type, private config: Routes, private urlTree: UrlTree, + private rootComponentType: Type|null, private config: Routes, private urlTree: UrlTree, private url: string) {} recognize(): Observable { @@ -38,8 +38,8 @@ class Recognizer { const children = this.processSegmentGroup(this.config, rootSegmentGroup, PRIMARY_OUTLET); const root = new ActivatedRouteSnapshot( - [], Object.freeze({}), Object.freeze(this.urlTree.queryParams), this.urlTree.fragment, {}, - PRIMARY_OUTLET, this.rootComponentType, null, this.urlTree.root, -1, {}); + [], Object.freeze({}), Object.freeze(this.urlTree.queryParams), this.urlTree.fragment !, + {}, PRIMARY_OUTLET, this.rootComponentType, null, this.urlTree.root, -1, {}); const rootNode = new TreeNode(root, children); const routeState = new RouterStateSnapshot(this.url, rootNode); @@ -110,10 +110,10 @@ class Recognizer { if ((route.outlet || PRIMARY_OUTLET) !== outlet) throw new NoMatch(); if (route.path === '**') { - const params = segments.length > 0 ? last(segments).parameters : {}; + const params = segments.length > 0 ? last(segments) !.parameters : {}; const snapshot = new ActivatedRouteSnapshot( - segments, params, Object.freeze(this.urlTree.queryParams), this.urlTree.fragment, - getData(route), outlet, route.component, route, getSourceSegmentGroup(rawSegment), + segments, params, Object.freeze(this.urlTree.queryParams), this.urlTree.fragment !, + getData(route), outlet, route.component !, route, getSourceSegmentGroup(rawSegment), getPathIndexShift(rawSegment) + segments.length, getResolve(route)); return [new TreeNode(snapshot, [])]; } @@ -127,7 +127,7 @@ class Recognizer { const snapshot = new ActivatedRouteSnapshot( 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, getResolve(route)); @@ -160,7 +160,7 @@ function getChildConfig(route: Route): Route[] { } if (route.loadChildren) { - return route._loadedConfig.routes; + return route._loadedConfig !.routes; } return []; @@ -180,7 +180,7 @@ function match(segmentGroup: UrlSegmentGroup, route: Route, segments: UrlSegment if (!res) throw new NoMatch(); 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}; return {consumedSegments: res.consumed, lastChild: res.consumed.length, parameters}; diff --git a/packages/router/src/route_reuse_strategy.ts b/packages/router/src/route_reuse_strategy.ts index f733b06dc6..3f96768bef 100644 --- a/packages/router/src/route_reuse_strategy.ts +++ b/packages/router/src/route_reuse_strategy.ts @@ -37,13 +37,13 @@ export abstract class RouteReuseStrategy { abstract shouldDetach(route: ActivatedRouteSnapshot): boolean; /** 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 */ abstract shouldAttach(route: ActivatedRouteSnapshot): boolean; /** Retrieves the previously stored route */ - abstract retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle; + abstract retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle|null; /** Determines if a route should be reused */ abstract shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean; diff --git a/packages/router/src/router.ts b/packages/router/src/router.ts index 92a815e854..4414600ab6 100644 --- a/packages/router/src/router.ts +++ b/packages/router/src/router.ts @@ -189,7 +189,7 @@ export type RouterHook = (snapshot: RouterStateSnapshot) => Observable; * @internal */ function defaultRouterHook(snapshot: RouterStateSnapshot): Observable { - return of (null); + return of (null) as any; } /** @@ -199,7 +199,7 @@ export class DefaultRouteReuseStrategy implements RouteReuseStrategy { shouldDetach(route: ActivatedRouteSnapshot): boolean { return false; } store(route: ActivatedRouteSnapshot, detachedTree: DetachedRouteHandle): void {} 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 { return future.routeConfig === curr.routeConfig; } @@ -218,7 +218,7 @@ export class Router { private currentUrlTree: UrlTree; private rawUrlTree: UrlTree; - private navigations = new BehaviorSubject(null); + private navigations = new BehaviorSubject(null !); private routerEvents = new Subject(); private currentRouterState: RouterState; @@ -263,7 +263,7 @@ export class Router { */ // TODO: vsavkin make internal after the final is out. constructor( - private rootComponentType: Type, private urlSerializer: UrlSerializer, + private rootComponentType: Type|null, private urlSerializer: UrlSerializer, private outletMap: RouterOutletMap, private location: Location, injector: Injector, loader: NgModuleFactoryLoader, compiler: Compiler, public config: Routes) { const onLoadStart = (r: Route) => this.triggerEvent(new RouteConfigLoadStart(r)); @@ -354,7 +354,7 @@ export class Router { dispose(): void { if (this.locationSubscription) { this.locationSubscription.unsubscribe(); - this.locationSubscription = null; + this.locationSubscription = null !; } } @@ -407,7 +407,7 @@ export class Router { } const a = relativeTo || this.routerState.root; const f = preserveFragment ? this.currentUrlTree.fragment : fragment; - let q: Params = null; + let q: Params|null = null; if (queryParamsHandling) { switch (queryParamsHandling) { case 'merge': @@ -417,12 +417,12 @@ export class Router { q = this.currentUrlTree.queryParams; break; default: - q = queryParams; + q = queryParams || null; } } 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. if (lastNavigation && source !== 'imperative' && lastNavigation.source === 'imperative' && 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 @@ -543,7 +543,7 @@ export class Router { // flicker. if (lastNavigation && source == 'hashchange' && lastNavigation.source === 'popstate' && 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; @@ -572,7 +572,7 @@ export class Router { Promise.resolve() .then( (_) => this.runNavigate( - url, rawUrl, extras.skipLocationChange, extras.replaceUrl, id, null)) + url, rawUrl, !!extras.skipLocationChange, !!extras.replaceUrl, id, null)) .then(resolve, reject); // we cannot process the current URL, but we could process the previous one => @@ -596,7 +596,7 @@ export class Router { private runNavigate( url: UrlTree, rawUrl: UrlTree, shouldPreventPushState: boolean, shouldReplaceUrl: boolean, - id: number, precreatedState: RouterStateSnapshot): Promise { + id: number, precreatedState: RouterStateSnapshot|null): Promise { if (id !== this.navigationId) { this.location.go(this.urlSerializer.serialize(this.currentUrlTree)); this.routerEvents.next(new NavigationCancel( @@ -768,7 +768,7 @@ class CanActivate { } 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( - futureNode: TreeNode, currNode: TreeNode, - outletMap: RouterOutletMap, futurePath: ActivatedRouteSnapshot[]): void { + futureNode: TreeNode, currNode: TreeNode|null, + outletMap: RouterOutletMap|null, futurePath: ActivatedRouteSnapshot[]): void { const prevChildren = nodeChildrenAsMap(currNode); futureNode.children.forEach(c => { @@ -814,12 +814,12 @@ export class PreActivation { }); forEach( prevChildren, (v: TreeNode, k: string) => - this.deactiveRouteAndItsChildren(v, outletMap._outlets[k])); + this.deactiveRouteAndItsChildren(v, outletMap !._outlets[k])); } private traverseRoutes( futureNode: TreeNode, currNode: TreeNode, - parentOutletMap: RouterOutletMap, futurePath: ActivatedRouteSnapshot[]): void { + parentOutletMap: RouterOutletMap|null, futurePath: ActivatedRouteSnapshot[]): void { const future = futureNode.value; const curr = currNode ? currNode.value : null; const outlet = parentOutletMap ? parentOutletMap._outlets[futureNode.value.outlet] : null; @@ -827,9 +827,9 @@ export class PreActivation { // reusing the node if (curr && future._routeConfig === curr._routeConfig) { if (this.shouldRunGuardsAndResolvers( - curr, future, future._routeConfig.runGuardsAndResolvers)) { + curr, future, future._routeConfig !.runGuardsAndResolvers)) { this.canActivateChecks.push(new CanActivate(futurePath)); - this.canDeactivateChecks.push(new CanDeactivate(outlet.component, curr)); + this.canDeactivateChecks.push(new CanDeactivate(outlet !.component, curr)); } else { // we need to set the data future.data = curr.data; @@ -864,7 +864,7 @@ export class PreActivation { private shouldRunGuardsAndResolvers( curr: ActivatedRouteSnapshot, future: ActivatedRouteSnapshot, - mode: RunGuardsAndResolvers): boolean { + mode: RunGuardsAndResolvers|undefined): boolean { switch (mode) { case 'always': return true; @@ -880,7 +880,7 @@ export class PreActivation { } private deactiveRouteAndItsChildren( - route: TreeNode, outlet: RouterOutlet): void { + route: TreeNode, outlet: RouterOutlet|null): void { const prevChildren = nodeChildrenAsMap(route); const r = route.value; @@ -958,13 +958,14 @@ export class PreActivation { } private extractCanActivateChild(p: ActivatedRouteSnapshot): - {node: ActivatedRouteSnapshot, guards: any[]} { + {node: ActivatedRouteSnapshot, guards: any[]}|null { const canActivateChild = p._routeConfig ? p._routeConfig.canActivateChild : null; if (!canActivateChild || canActivateChild.length === 0) return null; return {node: p, guards: canActivateChild}; } - private runCanDeactivate(component: Object, curr: ActivatedRouteSnapshot): Observable { + private runCanDeactivate(component: Object|null, curr: ActivatedRouteSnapshot): + Observable { const canDeactivate = curr && curr._routeConfig ? curr._routeConfig.canDeactivate : null; if (!canDeactivate || canDeactivate.length === 0) return of (true); const canDeactivate$ = mergeMap.call(from(canDeactivate), (c: any) => { @@ -1020,7 +1021,7 @@ class ActivateRoutes { } private deactivateChildRoutes( - futureNode: TreeNode, currNode: TreeNode, + futureNode: TreeNode, currNode: TreeNode|null, outletMap: RouterOutletMap): void { const prevChildren: {[key: string]: any} = nodeChildrenAsMap(currNode); futureNode.children.forEach(c => { @@ -1031,7 +1032,7 @@ class ActivateRoutes { } private activateChildRoutes( - futureNode: TreeNode, currNode: TreeNode, + futureNode: TreeNode, currNode: TreeNode|null, outletMap: RouterOutletMap): void { const prevChildren: {[key: string]: any} = nodeChildrenAsMap(currNode); futureNode.children.forEach( @@ -1136,7 +1137,7 @@ class ActivateRoutes { private deactiveRouteAndOutlet(route: TreeNode, parentOutletMap: RouterOutletMap): void { const prevChildren: {[key: string]: any} = nodeChildrenAsMap(route); - let outlet: RouterOutlet = null; + let outlet: RouterOutlet|null = null; // getOutlet throws when cannot find the right outlet, // which can happen if an outlet was in an NgIf and was removed @@ -1166,7 +1167,7 @@ function advanceActivatedRouteNodeAndItsChildren(node: TreeNode) node.children.forEach(advanceActivatedRouteNodeAndItsChildren); } -function parentLoadedConfig(snapshot: ActivatedRouteSnapshot): LoadedRouterConfig { +function parentLoadedConfig(snapshot: ActivatedRouteSnapshot): LoadedRouterConfig|null { for (let s = snapshot.parent; s; s = s.parent) { const route = s._routeConfig; if (route && route._loadedConfig) return route._loadedConfig; @@ -1176,7 +1177,7 @@ function parentLoadedConfig(snapshot: ActivatedRouteSnapshot): LoadedRouterConfi return null; } -function closestLoadedConfig(snapshot: ActivatedRouteSnapshot): LoadedRouterConfig { +function closestLoadedConfig(snapshot: ActivatedRouteSnapshot): LoadedRouterConfig|null { if (!snapshot) return null; for (let s = snapshot.parent; s; s = s.parent) { @@ -1187,7 +1188,7 @@ function closestLoadedConfig(snapshot: ActivatedRouteSnapshot): LoadedRouterConf return null; } -function nodeChildrenAsMap(node: TreeNode) { +function nodeChildrenAsMap(node: TreeNode| null) { const map: {[key: string]: TreeNode} = {}; if (node) { diff --git a/packages/router/src/router_config_loader.ts b/packages/router/src/router_config_loader.ts index b91bd28b5c..08d28c777a 100644 --- a/packages/router/src/router_config_loader.ts +++ b/packages/router/src/router_config_loader.ts @@ -32,7 +32,7 @@ export class RouterConfigLoader { this.onLoadStartListener(route); } - const moduleFactory$ = this.loadModuleFactory(route.loadChildren); + const moduleFactory$ = this.loadModuleFactory(route.loadChildren !); return map.call(moduleFactory$, (factory: NgModuleFactory) => { if (this.onLoadEndListener) { diff --git a/packages/router/src/router_module.ts b/packages/router/src/router_module.ts index 4451ac013f..a7c1c076ec 100644 --- a/packages/router/src/router_module.ts +++ b/packages/router/src/router_module.ts @@ -327,7 +327,7 @@ export class RouterInitializer { appInitializer(): Promise { const p: Promise = this.injector.get(LOCATION_INITIALIZED, Promise.resolve(null)); return p.then(() => { - let resolve: Function = null; + let resolve: Function = null !; const res = new Promise(r => resolve = r); const router = this.injector.get(Router); const opts = this.injector.get(ROUTER_CONFIGURATION); @@ -349,7 +349,7 @@ export class RouterInitializer { // subsequent navigations should not be delayed } else { - return of (null); + return of (null) as any; } }; router.initialNavigation(); @@ -380,7 +380,7 @@ export class RouterInitializer { preloader.setUpPreloading(); router.resetRootComponentType(ref.componentTypes[0]); - this.resultOfPreactivationDone.next(null); + this.resultOfPreactivationDone.next(null !); this.resultOfPreactivationDone.complete(); } diff --git a/packages/router/src/router_outlet_map.ts b/packages/router/src/router_outlet_map.ts index fb8e21c854..3fb1ad7a12 100644 --- a/packages/router/src/router_outlet_map.ts +++ b/packages/router/src/router_outlet_map.ts @@ -25,5 +25,5 @@ export class RouterOutletMap { /** * Removes an outlet from this map. */ - removeOutlet(name: string): void { this._outlets[name] = undefined; } + removeOutlet(name: string): void { this._outlets[name] = undefined !; } } diff --git a/packages/router/src/router_state.ts b/packages/router/src/router_state.ts index d37a321111..7b2f33be80 100644 --- a/packages/router/src/router_state.ts +++ b/packages/router/src/router_state.ts @@ -57,7 +57,7 @@ export class RouterState extends Tree { toString(): string { return this.snapshot.toString(); } } -export function createEmptyState(urlTree: UrlTree, rootComponent: Type): RouterState { +export function createEmptyState(urlTree: UrlTree, rootComponent: Type| null): RouterState { const snapshot = createEmptyStateSnapshot(urlTree, rootComponent); const emptyUrl = new BehaviorSubject([new UrlSegment('', {})]); const emptyParams = new BehaviorSubject({}); @@ -72,7 +72,7 @@ export function createEmptyState(urlTree: UrlTree, rootComponent: Type): Ro } export function createEmptyStateSnapshot( - urlTree: UrlTree, rootComponent: Type): RouterStateSnapshot { + urlTree: UrlTree, rootComponent: Type| null): RouterStateSnapshot { const emptyParams = {}; const emptyData = {}; const emptyQueryParams = {}; @@ -132,21 +132,21 @@ export class ActivatedRoute { public outlet: string, /** The component of the route. It's a constant */ // TODO(vsavkin): remove |string - public component: Type|string, futureSnapshot: ActivatedRouteSnapshot) { + public component: Type|string|null, futureSnapshot: ActivatedRouteSnapshot) { this._futureSnapshot = futureSnapshot; } /** 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 */ get root(): ActivatedRoute { return this._routerState.root; } /** 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 */ - 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 */ get children(): ActivatedRoute[] { return this._routerState.children(this); } @@ -234,7 +234,7 @@ export function inheritedParamsDataResolve(route: ActivatedRouteSnapshot): Inher */ export class ActivatedRouteSnapshot { /** @internal **/ - _routeConfig: Route; + _routeConfig: Route|null; /** @internal **/ _urlSegment: UrlSegmentGroup; /** @internal */ @@ -265,7 +265,7 @@ export class ActivatedRouteSnapshot { /** The outlet name of the route */ public outlet: string, /** The component of the route */ - public component: Type|string, routeConfig: Route, urlSegment: UrlSegmentGroup, + public component: Type|string|null, routeConfig: Route|null, urlSegment: UrlSegmentGroup, lastPathIndex: number, resolve: ResolveData) { this._routeConfig = routeConfig; this._urlSegment = urlSegment; @@ -274,16 +274,16 @@ export class ActivatedRouteSnapshot { } /** 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 */ get root(): ActivatedRouteSnapshot { return this._routerState.root; } /** 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 */ - 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 */ get children(): ActivatedRouteSnapshot[] { return this._routerState.children(this); } @@ -398,5 +398,5 @@ export function equalParamsAndUrlSegments( const parentsMismatch = !a.parent !== !b.parent; return equalUrlParams && !parentsMismatch && - (!a.parent || equalParamsAndUrlSegments(a.parent, b.parent)); -} + (!a.parent || equalParamsAndUrlSegments(a.parent, b.parent !)); +} \ No newline at end of file diff --git a/packages/router/src/shared.ts b/packages/router/src/shared.ts index d9897c9f6f..56814d5edd 100644 --- a/packages/router/src/shared.ts +++ b/packages/router/src/shared.ts @@ -111,7 +111,7 @@ export function isNavigationCancelingError(error: Error) { // Matches the route configuration (`route`) against the actual URL (`segments`). export function defaultUrlMatcher( segments: UrlSegment[], segmentGroup: UrlSegmentGroup, route: Route): UrlMatchResult|null { - const parts = route.path.split('/'); + const parts = route.path !.split('/'); if (parts.length > segments.length) { // The actual URL is shorter than the config, no match diff --git a/packages/router/src/url_tree.ts b/packages/router/src/url_tree.ts index 600f6bbb30..48a792d892 100644 --- a/packages/router/src/url_tree.ts +++ b/packages/router/src/url_tree.ts @@ -113,7 +113,7 @@ export class UrlTree { /** The query params of the URL */ public queryParams: {[key: string]: string}, /** The fragment of the URL */ - public fragment: string) {} + public fragment: string|null) {} get queryParamMap(): ParamMap { if (!this._queryParamMap) { @@ -139,7 +139,7 @@ export class UrlSegmentGroup { /** @internal */ _segmentIndexShift: number; /** The parent node in the url tree */ - parent: UrlSegmentGroup = null; + parent: UrlSegmentGroup|null = null; constructor( /** 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 { const segment = `/${serializeSegment(tree.root, true)}`; 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}`; } @@ -397,7 +397,9 @@ class UrlParser { 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} { if (this.remaining === '') { @@ -521,7 +523,7 @@ class UrlParser { throw new Error(`Cannot parse url '${this.url}'`); } - let outletName: string; + let outletName: string = undefined !; if (path.indexOf(':') > -1) { outletName = path.substr(0, path.indexOf(':')); this.capture(outletName); diff --git a/packages/router/src/utils/collection.ts b/packages/router/src/utils/collection.ts index fcc3fb58d0..c49a2daf8f 100644 --- a/packages/router/src/utils/collection.ts +++ b/packages/router/src/utils/collection.ts @@ -45,7 +45,7 @@ export function flatten(arr: T[][]): T[] { return Array.prototype.concat.apply([], arr); } -export function last(a: T[]): T { +export function last(a: T[]): T|null { return a.length > 0 ? a[a.length - 1] : null; } diff --git a/packages/router/src/utils/tree.ts b/packages/router/src/utils/tree.ts index 76a511a4ce..a21fee00ed 100644 --- a/packages/router/src/utils/tree.ts +++ b/packages/router/src/utils/tree.ts @@ -17,7 +17,7 @@ export class Tree { /** * @internal */ - parent(t: T): T { + parent(t: T): T|null { const p = this.pathFromRoot(t); return p.length > 1 ? p[p.length - 2] : null; } @@ -33,7 +33,7 @@ export class Tree { /** * @internal */ - firstChild(t: T): T { + firstChild(t: T): T|null { const n = findNode(t, this._root); return n && n.children.length > 0 ? n.children[0].value : null; } @@ -55,7 +55,7 @@ export class Tree { pathFromRoot(t: T): T[] { return findPath(t, this._root, []).map(s => s.value); } } -function findNode(expected: T, c: TreeNode): TreeNode { +function findNode(expected: T, c: TreeNode): TreeNode|null { if (expected === c.value) return c; for (const cc of c.children) { const r = findNode(expected, cc); diff --git a/packages/router/test/apply_redirects.spec.ts b/packages/router/test/apply_redirects.spec.ts index 5e1e044b1e..6583c1c5e0 100644 --- a/packages/router/test/apply_redirects.spec.ts +++ b/packages/router/test/apply_redirects.spec.ts @@ -51,7 +51,7 @@ describe('applyRedirects', () => { }); 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'} ]).subscribe(() => {}, (e) => { expect(e.message).toEqual('Cannot redirect to \'a/:other\'. Cannot find \':other\'.'); @@ -403,7 +403,7 @@ describe('applyRedirects', () => { {path: '', redirectTo: 'a', pathMatch: 'full'} ]; - applyRedirects(testModule.injector, null, serializer, tree('b'), config) + applyRedirects(testModule.injector, null !, serializer, tree('b'), config) .subscribe( (_) => { throw 'Should not be reached'; }, 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( (_) => { throw 'Should not be reached'; }, 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', () => { applyRedirects( - testModule.injector, null, serializer, tree('/a/c'), + testModule.injector, null !, serializer, tree('/a/c'), [{path: 'a', component: ComponentA, children: [{path: 'b', component: ComponentB}]}]) .subscribe( (_) => { throw 'Should not be reached'; }, @@ -587,7 +587,7 @@ describe('applyRedirects', () => { matcher: matcher, component: ComponentA, children: [{path: 'b', component: ComponentB}] - }], + }] as any, '/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', () => { applyRedirects( - testModule.injector, null, serializer, tree('a'), + testModule.injector, null !, serializer, tree('a'), [ {path: 'a', redirectTo: 'b(aux:c)'}, ]) @@ -629,7 +629,7 @@ describe('applyRedirects', () => { }); 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; }); } diff --git a/packages/router/test/bootstrap.spec.ts b/packages/router/test/bootstrap.spec.ts index 1c6dabfde9..d1f43c346f 100644 --- a/packages/router/test/bootstrap.spec.ts +++ b/packages/router/test/bootstrap.spec.ts @@ -16,7 +16,7 @@ import {NavigationEnd, Resolve, Router, RouterModule} from '@angular/router'; describe('bootstrap', () => { let log: any[] = []; - let testProviders: any[] = null; + let testProviders: any[] = null !; @Component({selector: 'test-app', template: 'root '}) class RootCmp { @@ -80,7 +80,7 @@ describe('bootstrap', () => { platformBrowserDynamic([]).bootstrapModule(TestModule).then(res => { 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(log).toEqual( ['TestModule', 'NavigationStart', 'RoutesRecognized', 'RootCmp', 'NavigationEnd']); diff --git a/packages/router/test/config.spec.ts b/packages/router/test/config.spec.ts index 5897da2539..ad643a8fae 100644 --- a/packages/router/test/config.spec.ts +++ b/packages/router/test/config.spec.ts @@ -24,7 +24,8 @@ describe('config', () => { it('should throw for undefined route', () => { 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 ''/); }); @@ -36,7 +37,7 @@ describe('config', () => { {path: 'b', component: ComponentB}, , ] - }]); + }] as any); }).toThrowError(/Invalid configuration of route 'a'/); }); @@ -98,7 +99,7 @@ describe('config', () => { }); it('should throw when path and matcher are missing', () => { - expect(() => { validateConfig([{component: null, redirectTo: 'b'}]); }) + expect(() => { validateConfig([{component: null, redirectTo: 'b'}] as any); }) .toThrowError( `Invalid configuration of route '': routes must have either a path or a matcher specified`); }); diff --git a/packages/router/test/create_router_state.spec.ts b/packages/router/test/create_router_state.spec.ts index b31247b4fc..49ed70f028 100644 --- a/packages/router/test/create_router_state.spec.ts +++ b/packages/router/test/create_router_state.spec.ts @@ -19,7 +19,7 @@ describe('create router state', () => { const reuseStrategy = new DefaultRouteReuseStrategy(); const emptyState = () => - createEmptyState(new UrlTree(new UrlSegmentGroup([], {}), {}, null), RootComponent); + createEmptyState(new UrlTree(new UrlSegmentGroup([], {}), {}, null !), RootComponent); it('should work create new state', () => { const state = createRouterState( @@ -76,8 +76,8 @@ describe('create router state', () => { createRouterState(reuseStrategy, createState(config, 'a/2;p=22/(b//right:c)'), prevState); expect(prevState.root).toBe(state.root); - const prevP = prevState.firstChild(prevState.root); - const currP = state.firstChild(state.root); + const prevP = prevState.firstChild(prevState.root) !; + const currP = state.firstChild(state.root) !; expect(prevP).toBe(currP); const prevC = prevState.children(prevP); @@ -101,7 +101,7 @@ function advanceNode(node: TreeNode): void { } function createState(config: Routes, url: string): RouterStateSnapshot { - let res: RouterStateSnapshot; + let res: RouterStateSnapshot = undefined !; recognize(RootComponent, config, tree(url), url).forEach(s => res = s); return res; } diff --git a/packages/router/test/create_url_tree.spec.ts b/packages/router/test/create_url_tree.spec.ts index bb7a2b3b00..726faff2bd 100644 --- a/packages/router/test/create_url_tree.spec.ts +++ b/packages/router/test/create_url_tree.spec.ts @@ -247,10 +247,10 @@ function createRoot(tree: UrlTree, commands: any[], queryParams?: Params, fragme [], {}, {}, '', {}, PRIMARY_OUTLET, 'someComponent', null, tree.root, -1, null); const a = new ActivatedRoute( - 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 !), new BehaviorSubject(null !), + new BehaviorSubject(null !), new BehaviorSubject(null !), PRIMARY_OUTLET, 'someComponent', s); advanceActivatedRoute(a); - return createUrlTree(a, tree, commands, queryParams, fragment); + return createUrlTree(a, tree, commands, queryParams !, fragment !); } function create( @@ -263,8 +263,8 @@ function create( [], {}, {}, '', {}, PRIMARY_OUTLET, 'someComponent', null, segment, startIndex, null); const a = new ActivatedRoute( - 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 !), new BehaviorSubject(null !), + new BehaviorSubject(null !), new BehaviorSubject(null !), PRIMARY_OUTLET, 'someComponent', s); advanceActivatedRoute(a); - return createUrlTree(a, tree, commands, queryParams, fragment); + return createUrlTree(a, tree, commands, queryParams !, fragment !); } \ No newline at end of file diff --git a/packages/router/test/integration.spec.ts b/packages/router/test/integration.spec.ts index 1a98a5dab2..940c1f856c 100644 --- a/packages/router/test/integration.spec.ts +++ b/packages/router/test/integration.spec.ts @@ -239,7 +239,7 @@ describe('Integration', () => { advance(fixture); let recordedError: any = null; - router.navigateByUrl('/blank').catch(e => recordedError = e); + router.navigateByUrl('/blank') !.catch(e => recordedError = e); advance(fixture); expect(recordedError.message).toEqual('Cannot find primary outlet to load \'BlankCmp\''); @@ -619,8 +619,8 @@ describe('Integration', () => { const user = fixture.debugElement.children[1].componentInstance; let r1: any, r2: any; - router.navigateByUrl('/user/victor').then(_ => r1 = _); - router.navigateByUrl('/user/fedor').then(_ => r2 = _); + router.navigateByUrl('/user/victor') !.then(_ => r1 = _); + router.navigateByUrl('/user/fedor') !.then(_ => r2 = _); advance(fixture); expect(r1).toEqual(false); // returns false because it was canceled @@ -649,7 +649,7 @@ describe('Integration', () => { router.events.forEach(e => recordedEvents.push(e)); let e: any; - router.navigateByUrl('/invalid').catch(_ => e = _); + router.navigateByUrl('/invalid') !.catch(_ => e = _); advance(fixture); expect(e.message).toContain('Cannot match any routes'); @@ -676,7 +676,7 @@ describe('Integration', () => { router.events.forEach(e => recordedEvents.push(e)); let e: any; - router.navigateByUrl('/invalid').then(_ => e = _); + router.navigateByUrl('/invalid') !.then(_ => e = _); advance(fixture); expect(e).toEqual('resolvedValue'); @@ -910,7 +910,7 @@ describe('Integration', () => { router.events.subscribe(e => recordedEvents.push(e)); let e: any = null; - router.navigateByUrl('/simple').catch(error => e = error); + router.navigateByUrl('/simple') !.catch(error => e = error); advance(fixture); expectEvents(recordedEvents, [ @@ -1687,7 +1687,7 @@ describe('Integration', () => { { provide: 'RecordingDeactivate', 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; } }, @@ -1735,14 +1735,14 @@ describe('Integration', () => { advance(fixture); expect(location.path()).toEqual('/team/22'); - let successStatus: boolean; - router.navigateByUrl('/team/33').then(res => successStatus = res); + let successStatus: boolean = false; + router.navigateByUrl('/team/33') !.then(res => successStatus = res); advance(fixture); expect(location.path()).toEqual('/team/33'); expect(successStatus).toEqual(true); - let canceledStatus: boolean; - router.navigateByUrl('/team/44').then(res => canceledStatus = res); + let canceledStatus: boolean = false; + router.navigateByUrl('/team/44') !.then(res => canceledStatus = res); advance(fixture); expect(location.path()).toEqual('/team/33'); expect(canceledStatus).toEqual(false); @@ -2072,7 +2072,7 @@ describe('Integration', () => { expect(location.path()).toEqual('/team/22'); - router.navigateByUrl('/team/33').catch(() => {}); + router.navigateByUrl('/team/33') !.catch(() => {}); advance(fixture); expect(location.path()).toEqual('/team/22'); @@ -2582,8 +2582,8 @@ describe('Integration', () => { expect(location.path()).toEqual('/lazy/parent/child'); expect(fixture.nativeElement).toHaveText('parent[child]'); - const pInj = fixture.debugElement.query(By.directive(Parent)).injector; - const cInj = fixture.debugElement.query(By.directive(Child)).injector; + const pInj = fixture.debugElement.query(By.directive(Parent)).injector !; + const cInj = fixture.debugElement.query(By.directive(Child)).injector !; expect(pInj.get('moduleName')).toEqual('parent'); expect(pInj.get('fromParent')).toEqual('from parent'); @@ -2769,7 +2769,7 @@ describe('Integration', () => { router.resetConfig([{path: 'lazy', loadChildren: 'expected'}]); let recordedError: any = null; - router.navigateByUrl('/lazy/loaded').catch(err => recordedError = err); + router.navigateByUrl('/lazy/loaded') !.catch(err => recordedError = err); advance(fixture); expect(recordedError.message) .toEqual( @@ -2942,7 +2942,7 @@ describe('Integration', () => { const recordedEvents: any[] = []; router.events.forEach(e => recordedEvents.push(e)); - router.navigateByUrl('/lazy/loaded').catch(s => {}); + router.navigateByUrl('/lazy/loaded') !.catch(s => {}); advance(fixture); expect(location.path()).toEqual('/'); @@ -3206,19 +3206,19 @@ describe('Integration', () => { stored: {[k: string]: DetachedRouteHandle} = {}; shouldDetach(route: ActivatedRouteSnapshot): boolean { - return route.routeConfig.path === 'a'; + return route.routeConfig !.path === 'a'; } store(route: ActivatedRouteSnapshot, detachedTree: DetachedRouteHandle): void { - this.stored[route.routeConfig.path] = detachedTree; + this.stored[route.routeConfig !.path !] = detachedTree; } shouldAttach(route: ActivatedRouteSnapshot): boolean { - return !!this.stored[route.routeConfig.path]; + return !!this.stored[route.routeConfig !.path !]; } retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle { - return this.stored[route.routeConfig.path]; + return this.stored[route.routeConfig !.path !]; } shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean { @@ -3230,7 +3230,7 @@ describe('Integration', () => { shouldDetach(route: ActivatedRouteSnapshot): boolean { return false; } store(route: ActivatedRouteSnapshot, detachedTree: DetachedRouteHandle): void {} shouldAttach(route: ActivatedRouteSnapshot): boolean { return false; } - retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle { return null; } + retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle { return null !; } shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean { if (future.routeConfig !== curr.routeConfig) { return false; diff --git a/packages/router/test/recognize.spec.ts b/packages/router/test/recognize.spec.ts index cf63d18b53..a90f99ecca 100644 --- a/packages/router/test/recognize.spec.ts +++ b/packages/router/test/recognize.spec.ts @@ -16,14 +16,14 @@ describe('recognize', () => { it('should work', () => { checkRecognize([{path: 'a', component: ComponentA}], 'a', (s: RouterStateSnapshot) => { checkActivatedRoute(s.root, '', {}, RootComponent); - checkActivatedRoute(s.firstChild(s.root), 'a', {}, ComponentA); + checkActivatedRoute(s.firstChild(s.root) !, 'a', {}, ComponentA); }); }); it('should freeze params object', () => { checkRecognize([{path: 'a/:id', component: ComponentA}], 'a/10', (s: RouterStateSnapshot) => { checkActivatedRoute(s.root, '', {}, RootComponent); - const child = s.firstChild(s.root); + const child = s.firstChild(s.root) !; expect(Object.isFrozen(child.params)).toBeTruthy(); }); }); @@ -79,11 +79,11 @@ describe('recognize', () => { expect(s.root._urlSegment).toBe(url.root); 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._lastPathIndex).toBe(1); - const compC = s.firstChild(compA); + const compC = s.firstChild(compA) !; expect(compC._urlSegment).toBe(url.root.children[PRIMARY_OUTLET]); expect(compC._lastPathIndex).toBe(2); }); @@ -101,11 +101,11 @@ describe('recognize', () => { expect(s.root._urlSegment).toBe(url.root); 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._lastPathIndex).toBe(0); - const compC = s.firstChild(compA); + const compC = s.firstChild(compA) !; expect(compC._urlSegment).toBe(url.root.children[PRIMARY_OUTLET]); expect(compC._lastPathIndex).toBe(2); }); @@ -119,16 +119,16 @@ describe('recognize', () => { ], 'a/paramA', (s: RouterStateSnapshot) => { checkActivatedRoute(s.root, '', {}, RootComponent); - checkActivatedRoute(s.firstChild(s.root), 'a', {}, ComponentA); + checkActivatedRoute(s.firstChild(s.root) !, 'a', {}, ComponentA); checkActivatedRoute( - s.firstChild(s.firstChild(s.root)), 'paramA', {id: 'paramA'}, ComponentB); + s.firstChild(s.firstChild(s.root)) !, 'paramA', {id: 'paramA'}, ComponentB); }); checkRecognize( [{path: 'a', component: ComponentA}, {path: 'a/:id', component: ComponentC}], 'a/paramA', (s: RouterStateSnapshot) => { 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) => { const c = s.children(s.root); checkActivatedRoute(c[0], 'a', {a1: '11', a2: '22'}, ComponentA); - checkActivatedRoute(s.firstChild(c[0]), 'b', {b1: '111', b2: '222'}, ComponentB); + checkActivatedRoute(s.firstChild(c[0]) !, 'b', {b1: '111', b2: '222'}, ComponentB); checkActivatedRoute(c[1], 'c', {c1: '1111', c2: '2222'}, ComponentC, 'left'); }); }); @@ -196,7 +196,7 @@ describe('recognize', () => { it('should set static data', () => { checkRecognize( [{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}); }); }); @@ -209,7 +209,7 @@ describe('recognize', () => { children: [{path: 'b', data: {two: 2}, component: ComponentB}] }], 'a/b', (s: RouterStateSnapshot) => { - const r: ActivatedRouteSnapshot = s.firstChild(s.firstChild(s.root)); + const r: ActivatedRouteSnapshot = s.firstChild(s.firstChild(s.root)) !; expect(r.data).toEqual({one: 1, two: 2}); }); }); @@ -218,7 +218,7 @@ describe('recognize', () => { checkRecognize( [{path: 'a', resolve: {one: 'some-token'}, component: ComponentA}], 'a', (s: RouterStateSnapshot) => { - const r: ActivatedRouteSnapshot = s.firstChild(s.root); + const r: ActivatedRouteSnapshot = s.firstChild(s.root) !; expect(r._resolve).toEqual({one: 'some-token'}); }); }); @@ -228,7 +228,7 @@ describe('recognize', () => { describe('root', () => { it('should work', () => { 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( [{path: '', pathMatch: 'full', component: ComponentA}], '', (s: RouterStateSnapshot) => { - checkActivatedRoute(s.firstChild(s.root), '', {}, ComponentA); + checkActivatedRoute(s.firstChild(s.root) !, '', {}, ComponentA); }); }); @@ -244,8 +244,8 @@ describe('recognize', () => { checkRecognize( [{path: '', component: ComponentA, children: [{path: '', component: ComponentB}]}], '', (s: RouterStateSnapshot) => { - checkActivatedRoute(s.firstChild(s.root), '', {}, ComponentA); - checkActivatedRoute(s.firstChild(s.firstChild(s.root)), '', {}, ComponentB); + checkActivatedRoute(s.firstChild(s.root) !, '', {}, ComponentA); + checkActivatedRoute(s.firstChild(s.firstChild(s.root)) !, '', {}, ComponentB); }); }); @@ -259,11 +259,11 @@ describe('recognize', () => { expect(s.root._urlSegment).toBe(url.root); 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._lastPathIndex).toBe(-1); - const c2 = s.firstChild(s.firstChild(s.root)); + const c2 = s.firstChild(s.firstChild(s.root)) !; expect(c2._urlSegment).toBe(url.root); expect(c2._lastPathIndex).toBe(-1); }); @@ -279,10 +279,10 @@ describe('recognize', () => { ] }], '/a;p=1', (s: RouterStateSnapshot) => { - checkActivatedRoute(s.firstChild(s.root), 'a', {p: '1'}, ComponentA); - checkActivatedRoute(s.firstChild(s.firstChild(s.root)), '', {p: '1'}, ComponentB); + 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.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) => { - 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[1], '', {}, ComponentC, 'aux'); }); @@ -330,13 +330,13 @@ describe('recognize', () => { checkRecognize(config, 'parent/b', (s: RouterStateSnapshot) => { 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[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) => { - 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); checkActivatedRoute(c[0], 'b', {}, ComponentB); }); @@ -375,11 +375,11 @@ describe('recognize', () => { expect(s.root._urlSegment).toBe(url.root); 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._lastPathIndex).toBe(0); - const b = s.firstChild(a); + const b = s.firstChild(a) !; expect(b._urlSegment).toBe(url.root.children[PRIMARY_OUTLET]); expect(b._lastPathIndex).toBe(1); @@ -403,15 +403,15 @@ describe('recognize', () => { expect(s.root._urlSegment).toBe(url.root); 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._lastPathIndex).toBe(0); - const b = s.firstChild(a); + const b = s.firstChild(a) !; expect(b._urlSegment).toBe(url.root.children[PRIMARY_OUTLET]); 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._lastPathIndex).toBe(0); }); @@ -431,15 +431,15 @@ describe('recognize', () => { expect(s.root._urlSegment).toBe(url.root); 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._lastPathIndex).toBe(-1); - const b = s.firstChild(a); + const b = s.firstChild(a) !; expect(b._urlSegment).toBe(url.root); expect(b._lastPathIndex).toBe(-1); - const c = s.firstChild(b); + const c = s.firstChild(b) !; expect(c._urlSegment).toBe(url.root); expect(c._lastPathIndex).toBe(-1); }); @@ -458,9 +458,9 @@ describe('recognize', () => { ] }], '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[1], '', {}, ComponentC, 'aux'); }); @@ -477,9 +477,9 @@ describe('recognize', () => { ] }], '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[1], '', {}, ComponentC, 'aux'); }); @@ -496,9 +496,9 @@ describe('recognize', () => { ] }], '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[1], 'c', {}, ComponentC, 'aux'); }); @@ -538,13 +538,13 @@ describe('recognize', () => { ] }], '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(s.firstChild(c[0]), 'd', {}, ComponentD); + checkActivatedRoute(s.firstChild(c[0]) !, 'd', {}, ComponentD); 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', () => { checkRecognize( [{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) => { - const p = s.firstChild(s.root); - checkActivatedRoute(p, 'p/11', {id: '11', pp: '22'}, undefined); + const p = s.firstChild(s.root) !; + checkActivatedRoute(p, 'p/11', {id: '11', pp: '22'}, undefined !); const c = s.children(p); 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) => { - const p = s.firstChild(s.root); - checkActivatedRoute(p, 'p/11', {id: '11'}, undefined); + const p = s.firstChild(s.root) !; + checkActivatedRoute(p, 'p/11', {id: '11'}, undefined !); - const a = s.firstChild(p); - checkActivatedRoute(a, 'a/victor', {id: '11', name: 'victor'}, undefined); + const a = s.firstChild(p) !; + 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); - const c = s.firstChild(b); + const c = s.firstChild(b) !; checkActivatedRoute(c, 'c', {}, ComponentC); }); }); @@ -614,7 +614,7 @@ describe('recognize', () => { [{path: 'a', component: ComponentA, children: [{path: 'b', component: ComponentB}]}], '/a', (s: RouterStateSnapshot) => { const a = s.firstChild(s.root); - checkActivatedRoute(a, 'a', {}, ComponentA); + checkActivatedRoute(a !, 'a', {}, ComponentA); }); }); @@ -629,7 +629,7 @@ describe('recognize', () => { ] }], '/a', (s: RouterStateSnapshot) => { - const a = s.firstChild(s.root); + const a = s.firstChild(s.root) !; checkActivatedRoute(a, 'a', {}, ComponentA); checkActivatedRoute(a.children[0], '', {}, ComponentC, 'aux'); }); @@ -651,11 +651,11 @@ describe('recognize', () => { matcher: matcher, component: ComponentA, children: [{path: 'b', component: ComponentB}] - }], + }] as any, '/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.firstChild, 'b', {}, ComponentB); + checkActivatedRoute(a.firstChild !, 'b', {}, ComponentB); }); }); }); diff --git a/packages/router/test/router.spec.ts b/packages/router/test/router.spec.ts index 6f293266ad..77b8984ee7 100644 --- a/packages/router/test/router.spec.ts +++ b/packages/router/test/router.spec.ts @@ -57,7 +57,7 @@ describe('Router', () => { const inj = {get: (token: any) => () => `${token}_value`}; let empty: RouterStateSnapshot; - beforeEach(() => { empty = createEmptyStateSnapshot(serializer.parse('/'), null); }); + beforeEach(() => { empty = createEmptyStateSnapshot(serializer.parse('/'), null !); }); it('should resolve data', () => { const r = {data: 'resolver'}; @@ -65,7 +65,7 @@ describe('Router', () => { const s = new RouterStateSnapshot('url', new TreeNode(empty.root, [new TreeNode(n, [])])); 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 childResolve = {}; - const parent = createActivatedRouteSnapshot(null, {resolve: parentResolve}); + const parent = createActivatedRouteSnapshot(null !, {resolve: parentResolve}); const child = createActivatedRouteSnapshot('b', {resolve: childResolve}); const s = new RouterStateSnapshot( @@ -82,7 +82,7 @@ describe('Router', () => { const inj = {get: (token: any) => () => Promise.resolve(`${token}_value`)}; 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( 'url', new TreeNode(empty.root, [new TreeNode(n21, [new TreeNode(n22, [])])])); checkResolveData(s2, s1, inj, () => { - expect(s2.root.firstChild.data).toEqual({data: 'resolver1_value'}); - expect(s2.root.firstChild.firstChild.data).toEqual({data: 'resolver2_value'}); + expect(s2.root.firstChild !.data).toEqual({data: 'resolver1_value'}); + expect(s2.root.firstChild !.firstChild !.data).toEqual({data: 'resolver2_value'}); }); }); }); diff --git a/packages/router/test/router_state.spec.ts b/packages/router/test/router_state.spec.ts index 6417c7d9d7..f813d6c050 100644 --- a/packages/router/test/router_state.spec.ts +++ b/packages/router/test/router_state.spec.ts @@ -39,17 +39,17 @@ describe('RouterState & Snapshot', () => { }); it('should return root', () => { - const b = state.root.firstChild; + const b = state.root.firstChild !; expect(b.root).toBe(state.root); }); it('should return parent', () => { - const b = state.root.firstChild; + const b = state.root.firstChild !; expect(b.parent).toBe(state.root); }); it('should return path from root', () => { - const b = state.root.firstChild; + const b = state.root.firstChild !; const p = b.pathFromRoot; expect(p[0]).toBe(state.root); expect(p[1]).toBe(b); @@ -81,17 +81,17 @@ describe('RouterState & Snapshot', () => { }); it('should return root', () => { - const b = state.root.firstChild; + const b = state.root.firstChild !; expect(b.root).toBe(state.root); }); it('should return parent', () => { - const b = state.root.firstChild; + const b = state.root.firstChild !; expect(b.parent).toBe(state.root); }); it('should return path from root', () => { - const b = state.root.firstChild; + const b = state.root.firstChild !; const p = b.pathFromRoot; expect(p[0]).toBe(state.root); expect(p[1]).toBe(b); @@ -102,7 +102,7 @@ describe('RouterState & Snapshot', () => { function createSnapshot(params: Params, url: UrlSegment[]): ActivatedRouteSnapshot { const snapshot = new ActivatedRouteSnapshot( url, params, null, null, null, null, null, null, null, - -1, null); + -1, null !); snapshot._routerState = new RouterStateSnapshot('', new TreeNode(snapshot, [])); return snapshot; } @@ -177,7 +177,7 @@ describe('RouterState & Snapshot', () => { const data = {}; const snapshot = new ActivatedRouteSnapshot( url, params, queryParams, fragment, data, null, null, null, null, -1, - null); + null !); const state = new RouterStateSnapshot('', new TreeNode(snapshot, [])); snapshot._routerState = state; return snapshot; @@ -200,7 +200,7 @@ describe('RouterState & Snapshot', () => { function createActivatedRouteSnapshot(cmp: string) { return new ActivatedRouteSnapshot( null, null, null, null, null, null, cmp, null, - null, -1, null); + null, -1, null !); } function createActivatedRoute(cmp: string) { diff --git a/packages/router/testing/src/router_testing_module.ts b/packages/router/testing/src/router_testing_module.ts index 379abe7186..11fb8bb5fa 100644 --- a/packages/router/testing/src/router_testing_module.ts +++ b/packages/router/testing/src/router_testing_module.ts @@ -86,7 +86,7 @@ export function setupTestingRouter( loader: NgModuleFactoryLoader, compiler: Compiler, injector: Injector, routes: Route[][], urlHandlingStrategy?: UrlHandlingStrategy) { const router = new Router( - null, urlSerializer, outletMap, location, injector, loader, compiler, flatten(routes)); + null !, urlSerializer, outletMap, location, injector, loader, compiler, flatten(routes)); if (urlHandlingStrategy) { router.urlHandlingStrategy = urlHandlingStrategy; } diff --git a/packages/router/tsconfig-build.json b/packages/router/tsconfig-build.json index 5dd5e957d4..5cca1d6c13 100644 --- a/packages/router/tsconfig-build.json +++ b/packages/router/tsconfig-build.json @@ -10,6 +10,7 @@ "noEmitOnError": false, "noImplicitAny": true, "noImplicitReturns": true, + "strictNullChecks": true, "outDir": "../../dist/packages/router", "paths": { "@angular/core": ["../../dist/packages/core"], diff --git a/tools/public_api_guard/router/router.d.ts b/tools/public_api_guard/router/router.d.ts index 0387427f58..6dc3d5d2fa 100644 --- a/tools/public_api_guard/router/router.d.ts +++ b/tools/public_api_guard/router/router.d.ts @@ -1,19 +1,19 @@ /** @stable */ export declare class ActivatedRoute { readonly children: ActivatedRoute[]; - component: Type | string; + component: Type | string | null; data: Observable; - readonly firstChild: ActivatedRoute; + readonly firstChild: ActivatedRoute | null; fragment: Observable; outlet: string; readonly paramMap: Observable; params: Observable; - readonly parent: ActivatedRoute; + readonly parent: ActivatedRoute | null; readonly pathFromRoot: ActivatedRoute[]; readonly queryParamMap: Observable; queryParams: Observable; readonly root: ActivatedRoute; - readonly routeConfig: Route; + readonly routeConfig: Route | null; snapshot: ActivatedRouteSnapshot; url: Observable; toString(): string; @@ -22,19 +22,19 @@ export declare class ActivatedRoute { /** @stable */ export declare class ActivatedRouteSnapshot { readonly children: ActivatedRouteSnapshot[]; - component: Type | string; + component: Type | string | null; data: Data; - readonly firstChild: ActivatedRouteSnapshot; + readonly firstChild: ActivatedRouteSnapshot | null; fragment: string; outlet: string; readonly paramMap: ParamMap; params: Params; - readonly parent: ActivatedRouteSnapshot; + readonly parent: ActivatedRouteSnapshot | null; readonly pathFromRoot: ActivatedRouteSnapshot[]; readonly queryParamMap: ParamMap; queryParams: Params; readonly root: ActivatedRouteSnapshot; - readonly routeConfig: Route; + readonly routeConfig: Route | null; url: UrlSegment[]; toString(): string; } @@ -239,7 +239,7 @@ export declare class Router { readonly routerState: RouterState; readonly url: string; urlHandlingStrategy: UrlHandlingStrategy; - constructor(rootComponentType: Type, urlSerializer: UrlSerializer, outletMap: RouterOutletMap, location: Location, injector: Injector, loader: NgModuleFactoryLoader, compiler: Compiler, config: Routes); + constructor(rootComponentType: Type | 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; dispose(): void; initialNavigation(): void; @@ -261,11 +261,11 @@ export declare const ROUTER_INITIALIZER: InjectionToken<(compRef: ComponentRef