Skip to content

Commit e4f4d18

Browse files
atscottalxhub
authored andcommittedSep 25, 2020
refactor(router): Adjust type of parameter in navigateByUrl and createUrlTree to be more accurate (#38227)
`router.navigateByUrl` and `router.createUrlTree` only use a subset of the `NavigationExtras`. This commit changes the parameter type to use new interfaces that only specify the properties used by those function implementations. `NavigationExtras` extends both of those interfaces. Fixes #18798 BREAKING CHANGE: While the new parameter types allow a variable of type `NavigationExtras` to be passed in, they will not allow object literals, as they may only specify known properties. They will also not accept types that do not have properties in common with the ones in the `Pick`. To fix this error, only specify properties from the `NavigationExtras` which are actually used in the respective function calls or use a type assertion on the object or variable: `as NavigationExtras`. PR Close #38227
1 parent 837889f commit e4f4d18

File tree

6 files changed

+118
-63
lines changed

6 files changed

+118
-63
lines changed
 

‎aio/content/guide/deprecations.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ Tip: In the [API reference section](api) of this doc site, deprecated APIs are i
122122

123123
| API | Replacement | Deprecation announced | Notes |
124124
| --- | ----------- | --------------------- | ----- |
125-
| [`preserveQueryParams`](api/router/NavigationExtras#preserveQueryParams) | [`queryParamsHandling`](api/router/NavigationExtras#queryParamsHandling) | v4 | none |
125+
| [`preserveQueryParams`](api/router/UrlCreationOptions#preserveQueryParams) | [`queryParamsHandling`](api/router/UrlCreationOptions#queryParamsHandling) | v4 | none |
126126

127127
{@a platform-webworker}
128128
### @angular/platform-webworker

‎goldens/public-api/router/router.d.ts

+20-14
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,14 @@ export declare type Navigation = {
172172
previousNavigation: Navigation | null;
173173
};
174174

175+
export declare interface NavigationBehaviorOptions {
176+
replaceUrl?: boolean;
177+
skipLocationChange?: boolean;
178+
state?: {
179+
[k: string]: any;
180+
};
181+
}
182+
175183
export declare class NavigationCancel extends RouterEvent {
176184
reason: string;
177185
constructor(
@@ -199,18 +207,7 @@ export declare class NavigationError extends RouterEvent {
199207
toString(): string;
200208
}
201209

202-
export declare interface NavigationExtras {
203-
fragment?: string;
204-
preserveFragment?: boolean;
205-
/** @deprecated */ preserveQueryParams?: boolean;
206-
queryParams?: Params | null;
207-
queryParamsHandling?: QueryParamsHandling | null;
208-
relativeTo?: ActivatedRoute | null;
209-
replaceUrl?: boolean;
210-
skipLocationChange?: boolean;
211-
state?: {
212-
[k: string]: any;
213-
};
210+
export declare interface NavigationExtras extends UrlCreationOptions, NavigationBehaviorOptions {
214211
}
215212

216213
export declare class NavigationStart extends RouterEvent {
@@ -344,13 +341,13 @@ export declare class Router {
344341
urlHandlingStrategy: UrlHandlingStrategy;
345342
urlUpdateStrategy: 'deferred' | 'eager';
346343
constructor(rootComponentType: Type<any> | null, urlSerializer: UrlSerializer, rootContexts: ChildrenOutletContexts, location: Location, injector: Injector, loader: NgModuleFactoryLoader, compiler: Compiler, config: Routes);
347-
createUrlTree(commands: any[], navigationExtras?: NavigationExtras): UrlTree;
344+
createUrlTree(commands: any[], navigationExtras?: UrlCreationOptions): UrlTree;
348345
dispose(): void;
349346
getCurrentNavigation(): Navigation | null;
350347
initialNavigation(): void;
351348
isActive(url: string | UrlTree, exact: boolean): boolean;
352349
navigate(commands: any[], extras?: NavigationExtras): Promise<boolean>;
353-
navigateByUrl(url: string | UrlTree, extras?: NavigationExtras): Promise<boolean>;
350+
navigateByUrl(url: string | UrlTree, extras?: NavigationBehaviorOptions): Promise<boolean>;
354351
ngOnDestroy(): void;
355352
parseUrl(url: string): UrlTree;
356353
resetConfig(config: Routes): void;
@@ -502,6 +499,15 @@ export declare class Scroll {
502499
toString(): string;
503500
}
504501

502+
export declare interface UrlCreationOptions {
503+
fragment?: string;
504+
preserveFragment?: boolean;
505+
/** @deprecated */ preserveQueryParams?: boolean;
506+
queryParams?: Params | null;
507+
queryParamsHandling?: QueryParamsHandling | null;
508+
relativeTo?: ActivatedRoute | null;
509+
}
510+
505511
export declare abstract class UrlHandlingStrategy {
506512
abstract extract(url: UrlTree): UrlTree;
507513
abstract merge(newUrlPart: UrlTree, rawUrl: UrlTree): UrlTree;

‎packages/router/src/config.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ export type DeprecatedLoadChildren = string;
140140
* - `merge` : Merge new with current parameters.
141141
* - `preserve` : Preserve current parameters.
142142
*
143-
* @see `NavigationExtras#queryParamsHandling`
143+
* @see `UrlCreationOptions#queryParamsHandling`
144144
* @see `RouterLink`
145145
* @publicApi
146146
*/

‎packages/router/src/directives/router_link.ts

+49-35
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ import {UrlTree} from '../url_tree';
8484
* </a>
8585
* ```
8686
*
87-
* See {@link NavigationExtras.queryParamsHandling NavigationExtras#queryParamsHandling}.
87+
* See {@link UrlCreationOptions.queryParamsHandling UrlCreationOptions#queryParamsHandling}.
8888
*
8989
* ### Preserving navigation history
9090
*
@@ -117,51 +117,58 @@ import {UrlTree} from '../url_tree';
117117
@Directive({selector: ':not(a):not(area)[routerLink]'})
118118
export class RouterLink implements OnChanges {
119119
/**
120-
* Passed to {@link Router#createUrlTree Router#createUrlTree} as part of the `NavigationExtras`.
121-
* @see {@link NavigationExtras#queryParams NavigationExtras#queryParams}
120+
* Passed to {@link Router#createUrlTree Router#createUrlTree} as part of the
121+
* `UrlCreationOptions`.
122+
* @see {@link UrlCreationOptions#queryParams UrlCreationOptions#queryParams}
122123
* @see {@link Router#createUrlTree Router#createUrlTree}
123124
*/
124125
// TODO(issue/24571): remove '!'.
125126
@Input() queryParams!: {[k: string]: any};
126127
/**
127-
* Passed to {@link Router#createUrlTree Router#createUrlTree} as part of the `NavigationExtras`.
128-
* @see {@link NavigationExtras#fragment NavigationExtras#fragment}
128+
* Passed to {@link Router#createUrlTree Router#createUrlTree} as part of the
129+
* `UrlCreationOptions`.
130+
* @see {@link UrlCreationOptions#fragment UrlCreationOptions#fragment}
129131
* @see {@link Router#createUrlTree Router#createUrlTree}
130132
*/
131133
// TODO(issue/24571): remove '!'.
132134
@Input() fragment!: string;
133135
/**
134-
* Passed to {@link Router#createUrlTree Router#createUrlTree} as part of the `NavigationExtras`.
135-
* @see {@link NavigationExtras#queryParamsHandling NavigationExtras#queryParamsHandling}
136+
* Passed to {@link Router#createUrlTree Router#createUrlTree} as part of the
137+
* `UrlCreationOptions`.
138+
* @see {@link UrlCreationOptions#queryParamsHandling UrlCreationOptions#queryParamsHandling}
136139
* @see {@link Router#createUrlTree Router#createUrlTree}
137140
*/
138141
// TODO(issue/24571): remove '!'.
139142
@Input() queryParamsHandling!: QueryParamsHandling;
140143
/**
141-
* Passed to {@link Router#createUrlTree Router#createUrlTree} as part of the `NavigationExtras`.
142-
* @see {@link NavigationExtras#preserveFragment NavigationExtras#preserveFragment}
144+
* Passed to {@link Router#createUrlTree Router#createUrlTree} as part of the
145+
* `UrlCreationOptions`.
146+
* @see {@link UrlCreationOptions#preserveFragment UrlCreationOptions#preserveFragment}
143147
* @see {@link Router#createUrlTree Router#createUrlTree}
144148
*/
145149
// TODO(issue/24571): remove '!'.
146150
@Input() preserveFragment!: boolean;
147151
/**
148-
* Passed to {@link Router#createUrlTree Router#createUrlTree} as part of the `NavigationExtras`.
149-
* @see {@link NavigationExtras#skipLocationChange NavigationExtras#skipLocationChange}
150-
* @see {@link Router#createUrlTree Router#createUrlTree}
152+
* Passed to {@link Router#navigateByUrl Router#navigateByUrl} as part of the
153+
* `NavigationBehaviorOptions`.
154+
* @see {@link NavigationBehaviorOptions#skipLocationChange NavigationBehaviorOptions#skipLocationChange}
155+
* @see {@link Router#navigateByUrl Router#navigateByUrl}
151156
*/
152157
// TODO(issue/24571): remove '!'.
153158
@Input() skipLocationChange!: boolean;
154159
/**
155-
* Passed to {@link Router#createUrlTree Router#createUrlTree} as part of the `NavigationExtras`.
156-
* @see {@link NavigationExtras#replaceUrl NavigationExtras#replaceUrl}
157-
* @see {@link Router#createUrlTree Router#createUrlTree}
160+
* Passed to {@link Router#navigateByUrl Router#navigateByUrl} as part of the
161+
* `NavigationBehaviorOptions`.
162+
* @see {@link NavigationBehaviorOptions#replaceUrl NavigationBehaviorOptions#replaceUrl}
163+
* @see {@link Router#navigateByUrl Router#navigateByUrl}
158164
*/
159165
// TODO(issue/24571): remove '!'.
160166
@Input() replaceUrl!: boolean;
161167
/**
162-
* Passed to {@link Router#createUrlTree Router#createUrlTree} as part of the `NavigationExtras`.
163-
* @see {@link NavigationExtras#state NavigationExtras#state}
164-
* @see {@link Router#createUrlTree Router#createUrlTree}
168+
* Passed to {@link Router#navigateByUrl Router#navigateByUrl} as part of the
169+
* `NavigationBehaviorOptions`.
170+
* @see {@link NavigationBehaviorOptions#state NavigationBehaviorOptions#state}
171+
* @see {@link Router#navigateByUrl Router#navigateByUrl}
165172
*/
166173
@Input() state?: {[k: string]: any};
167174
private commands: any[] = [];
@@ -252,51 +259,58 @@ export class RouterLinkWithHref implements OnChanges, OnDestroy {
252259
// TODO(issue/24571): remove '!'.
253260
@HostBinding('attr.target') @Input() target!: string;
254261
/**
255-
* Passed to {@link Router#createUrlTree Router#createUrlTree} as part of the `NavigationExtras`.
256-
* @see {@link NavigationExtras#queryParams NavigationExtras#queryParams}
262+
* Passed to {@link Router#createUrlTree Router#createUrlTree} as part of the
263+
* `UrlCreationOptions`.
264+
* @see {@link UrlCreationOptions#queryParams UrlCreationOptions#queryParams}
257265
* @see {@link Router#createUrlTree Router#createUrlTree}
258266
*/
259267
// TODO(issue/24571): remove '!'.
260268
@Input() queryParams!: {[k: string]: any};
261269
/**
262-
* Passed to {@link Router#createUrlTree Router#createUrlTree} as part of the `NavigationExtras`.
263-
* @see {@link NavigationExtras#fragment NavigationExtras#fragment}
270+
* Passed to {@link Router#createUrlTree Router#createUrlTree} as part of the
271+
* `UrlCreationOptions`.
272+
* @see {@link UrlCreationOptions#fragment UrlCreationOptions#fragment}
264273
* @see {@link Router#createUrlTree Router#createUrlTree}
265274
*/
266275
// TODO(issue/24571): remove '!'.
267276
@Input() fragment!: string;
268277
/**
269-
* Passed to {@link Router#createUrlTree Router#createUrlTree} as part of the `NavigationExtras`.
270-
* @see {@link NavigationExtras#queryParamsHandling NavigationExtras#queryParamsHandling}
278+
* Passed to {@link Router#createUrlTree Router#createUrlTree} as part of the
279+
* `UrlCreationOptions`.
280+
* @see {@link UrlCreationOptions#queryParamsHandling UrlCreationOptions#queryParamsHandling}
271281
* @see {@link Router#createUrlTree Router#createUrlTree}
272282
*/
273283
// TODO(issue/24571): remove '!'.
274284
@Input() queryParamsHandling!: QueryParamsHandling;
275285
/**
276-
* Passed to {@link Router#createUrlTree Router#createUrlTree} as part of the `NavigationExtras`.
277-
* @see {@link NavigationExtras#preserveFragment NavigationExtras#preserveFragment}
286+
* Passed to {@link Router#createUrlTree Router#createUrlTree} as part of the
287+
* `UrlCreationOptions`.
288+
* @see {@link UrlCreationOptions#preserveFragment UrlCreationOptions#preserveFragment}
278289
* @see {@link Router#createUrlTree Router#createUrlTree}
279290
*/
280291
// TODO(issue/24571): remove '!'.
281292
@Input() preserveFragment!: boolean;
282293
/**
283-
* Passed to {@link Router#createUrlTree Router#createUrlTree} as part of the `NavigationExtras`.
284-
* @see {@link NavigationExtras#skipLocationChange NavigationExtras#skipLocationChange}
285-
* @see {@link Router#createUrlTree Router#createUrlTree}
294+
* Passed to {@link Router#navigateByUrl Router#navigateByUrl} as part of the
295+
* `NavigationBehaviorOptions`.
296+
* @see {@link NavigationBehaviorOptions#skipLocationChange NavigationBehaviorOptions#skipLocationChange}
297+
* @see {@link Router#navigateByUrl Router#navigateByUrl}
286298
*/
287299
// TODO(issue/24571): remove '!'.
288300
@Input() skipLocationChange!: boolean;
289301
/**
290-
* Passed to {@link Router#createUrlTree Router#createUrlTree} as part of the `NavigationExtras`.
291-
* @see {@link NavigationExtras#replaceUrl NavigationExtras#replaceUrl}
292-
* @see {@link Router#createUrlTree Router#createUrlTree}
302+
* Passed to {@link Router#navigateByUrl Router#navigateByUrl} as part of the
303+
* `NavigationBehaviorOptions`.
304+
* @see {@link NavigationBehaviorOptions#replaceUrl NavigationBehaviorOptions#replaceUrl}
305+
* @see {@link Router#navigateByUrl Router#navigateByUrl}
293306
*/
294307
// TODO(issue/24571): remove '!'.
295308
@Input() replaceUrl!: boolean;
296309
/**
297-
* Passed to {@link Router#createUrlTree Router#createUrlTree} as part of the `NavigationExtras`.
298-
* @see {@link NavigationExtras#state NavigationExtras#state}
299-
* @see {@link Router#createUrlTree Router#createUrlTree}
310+
* Passed to {@link Router#navigateByUrl Router#navigateByUrl} as part of the
311+
* `NavigationBehaviorOptions`.
312+
* @see {@link NavigationBehaviorOptions#state NavigationBehaviorOptions#state}
313+
* @see {@link Router#navigateByUrl Router#navigateByUrl}
300314
*/
301315
@Input() state?: {[k: string]: any};
302316
private commands: any[] = [];

‎packages/router/src/index.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export {RouterOutlet} from './directives/router_outlet';
1414
export {ActivationEnd, ActivationStart, ChildActivationEnd, ChildActivationStart, Event, GuardsCheckEnd, GuardsCheckStart, NavigationCancel, NavigationEnd, NavigationError, NavigationStart, ResolveEnd, ResolveStart, RouteConfigLoadEnd, RouteConfigLoadStart, RouterEvent, RoutesRecognized, Scroll} from './events';
1515
export {CanActivate, CanActivateChild, CanDeactivate, CanLoad, Resolve} from './interfaces';
1616
export {BaseRouteReuseStrategy, DetachedRouteHandle, RouteReuseStrategy} from './route_reuse_strategy';
17-
export {Navigation, NavigationExtras, Router} from './router';
17+
export {Navigation, NavigationBehaviorOptions, NavigationExtras, Router, UrlCreationOptions} from './router';
1818
export {ROUTES} from './router_config_loader';
1919
export {ExtraOptions, InitialNavigation, provideRoutes, ROUTER_CONFIGURATION, ROUTER_INITIALIZER, RouterModule} from './router_module';
2020
export {ChildrenOutletContexts, OutletContext} from './router_outlet_context';

‎packages/router/src/router.ts

+46-11
Original file line numberDiff line numberDiff line change
@@ -33,21 +33,21 @@ import {Checks, getAllRouteGuards} from './utils/preactivation';
3333
import {isUrlTree} from './utils/type_guards';
3434

3535

36+
3637
/**
3738
* @description
3839
*
39-
* Options that modify the `Router` navigation strategy.
40+
* Options that modify the `Router` URL.
4041
* Supply an object containing any of these properties to a `Router` navigation function to
41-
* control how the target URL should be constructed or interpreted.
42+
* control how the target URL should be constructed.
4243
*
4344
* @see [Router.navigate() method](api/router/Router#navigate)
44-
* @see [Router.navigateByUrl() method](api/router/Router#navigatebyurl)
4545
* @see [Router.createUrlTree() method](api/router/Router#createurltree)
4646
* @see [Routing and Navigation guide](guide/router)
4747
*
4848
* @publicApi
4949
*/
50-
export interface NavigationExtras {
50+
export interface UrlCreationOptions {
5151
/**
5252
* Specifies a root URI to use for relative navigation.
5353
*
@@ -135,6 +135,7 @@ export interface NavigationExtras {
135135
*
136136
*/
137137
queryParamsHandling?: QueryParamsHandling|null;
138+
138139
/**
139140
* When true, preserves the URL fragment for the next navigation
140141
*
@@ -144,6 +145,22 @@ export interface NavigationExtras {
144145
* ```
145146
*/
146147
preserveFragment?: boolean;
148+
}
149+
150+
/**
151+
* @description
152+
*
153+
* Options that modify the `Router` navigation strategy.
154+
* Supply an object containing any of these properties to a `Router` navigation function to
155+
* control how the navigation should be handled.
156+
*
157+
* @see [Router.navigate() method](api/router/Router#navigate)
158+
* @see [Router.navigateByUrl() method](api/router/Router#navigatebyurl)
159+
* @see [Routing and Navigation guide](guide/router)
160+
*
161+
* @publicApi
162+
*/
163+
export interface NavigationBehaviorOptions {
147164
/**
148165
* When true, navigates without pushing a new state into history.
149166
*
@@ -153,6 +170,7 @@ export interface NavigationExtras {
153170
* ```
154171
*/
155172
skipLocationChange?: boolean;
173+
156174
/**
157175
* When true, navigates while replacing the current state in history.
158176
*
@@ -162,6 +180,7 @@ export interface NavigationExtras {
162180
* ```
163181
*/
164182
replaceUrl?: boolean;
183+
165184
/**
166185
* Developer-defined state that can be passed to any navigation.
167186
* Access this value through the `Navigation.extras` object
@@ -180,6 +199,24 @@ export interface NavigationExtras {
180199
state?: {[k: string]: any};
181200
}
182201

202+
/**
203+
* @description
204+
*
205+
* Options that modify the `Router` navigation strategy.
206+
* Supply an object containing any of these properties to a `Router` navigation function to
207+
* control how the target URL should be constructed or interpreted.
208+
*
209+
* @see [Router.navigate() method](api/router/Router#navigate)
210+
* @see [Router.navigateByUrl() method](api/router/Router#navigatebyurl)
211+
* @see [Router.createUrlTree() method](api/router/Router#createurltree)
212+
* @see [Routing and Navigation guide](guide/router)
213+
* @see UrlCreationOptions
214+
* @see NavigationBehaviorOptions
215+
*
216+
* @publicApi
217+
*/
218+
export interface NavigationExtras extends UrlCreationOptions, NavigationBehaviorOptions {}
219+
183220
/**
184221
* Error handler that is invoked when a navigation error occurs.
185222
*
@@ -1030,8 +1067,7 @@ export class Router {
10301067
* segments, followed by the parameters for each segment.
10311068
* The fragments are applied to the current URL tree or the one provided in the `relativeTo`
10321069
* property of the options object, if supplied.
1033-
* @param navigationExtras Options that control the navigation strategy. This function
1034-
* only uses properties in `NavigationExtras` that would change the provided URL.
1070+
* @param navigationExtras Options that control the navigation strategy.
10351071
* @returns The new URL tree.
10361072
*
10371073
* @usageNotes
@@ -1068,7 +1104,7 @@ export class Router {
10681104
* router.createUrlTree(['../../team/44/user/22'], {relativeTo: route});
10691105
* ```
10701106
*/
1071-
createUrlTree(commands: any[], navigationExtras: NavigationExtras = {}): UrlTree {
1107+
createUrlTree(commands: any[], navigationExtras: UrlCreationOptions = {}): UrlTree {
10721108
const {
10731109
relativeTo,
10741110
queryParams,
@@ -1110,8 +1146,6 @@ export class Router {
11101146
* @param url An absolute path for a defined route. The function does not apply any delta to the
11111147
* current URL.
11121148
* @param extras An object containing properties that modify the navigation strategy.
1113-
* The function ignores any properties in the `NavigationExtras` that would change the
1114-
* provided URL.
11151149
*
11161150
* @returns A Promise that resolves to 'true' when navigation succeeds,
11171151
* to 'false' when navigation fails, or is rejected on error.
@@ -1130,8 +1164,9 @@ export class Router {
11301164
* @see [Routing and Navigation guide](guide/router)
11311165
*
11321166
*/
1133-
navigateByUrl(url: string|UrlTree, extras: NavigationExtras = {skipLocationChange: false}):
1134-
Promise<boolean> {
1167+
navigateByUrl(url: string|UrlTree, extras: NavigationBehaviorOptions = {
1168+
skipLocationChange: false
1169+
}): Promise<boolean> {
11351170
if (typeof ngDevMode === 'undefined' ||
11361171
ngDevMode && this.isNgZoneEnabled && !NgZone.isInAngularZone()) {
11371172
this.console.warn(

0 commit comments

Comments
 (0)
Please sign in to comment.