@@ -12,6 +12,10 @@ import type {
12
12
Transition
13
13
} from "history" ;
14
14
15
+ type Mutable < T > = {
16
+ - readonly [ P in keyof T ] : T [ P ] ;
17
+ } ;
18
+
15
19
const readOnly : < T > ( obj : T ) => Readonly < T > = __DEV__
16
20
? obj => Object . freeze ( obj )
17
21
: obj => obj ;
@@ -87,9 +91,9 @@ const RouteContext = React.createContext<RouteContextObject>({
87
91
route : null
88
92
} ) ;
89
93
90
- interface RouteContextObject {
94
+ interface RouteContextObject < ParamKey extends string = string > {
91
95
outlet : React . ReactElement | null ;
92
- params : Params ;
96
+ params : Params < ParamKey > ;
93
97
pathname : string ;
94
98
basename : string ;
95
99
route : RouteObject | null ;
@@ -374,7 +378,9 @@ export function useLocation(): Location {
374
378
*
375
379
* @see https://reactrouter.com/api/useMatch
376
380
*/
377
- export function useMatch ( pattern : PathPattern ) : PathMatch | null {
381
+ export function useMatch < ParamKey extends string = string > (
382
+ pattern : PathPattern
383
+ ) : PathMatch < ParamKey > | null {
378
384
invariant (
379
385
useInRouterContext ( ) ,
380
386
// TODO: This error is probably because they somehow have 2 versions of the
@@ -383,7 +389,7 @@ export function useMatch(pattern: PathPattern): PathMatch | null {
383
389
) ;
384
390
385
391
let location = useLocation ( ) as Location ;
386
- return matchPath ( pattern , location . pathname ) ;
392
+ return matchPath < ParamKey > ( pattern , location . pathname ) ;
387
393
}
388
394
389
395
type PathPattern =
@@ -468,7 +474,7 @@ export function useOutlet(): React.ReactElement | null {
468
474
*
469
475
* @see https://reactrouter.com/api/useParams
470
476
*/
471
- export function useParams ( ) : Params {
477
+ export function useParams < Key extends string = string > ( ) : Params < Key > {
472
478
return React . useContext ( RouteContext ) . params ;
473
479
}
474
480
@@ -666,7 +672,9 @@ export function createRoutesFromChildren(
666
672
/**
667
673
* The parameters that were parsed from the URL path.
668
674
*/
669
- export type Params = Record < string , string > ;
675
+ export type Params < Key extends string = string > = {
676
+ readonly [ key in Key ] : string | undefined ;
677
+ } ;
670
678
671
679
/**
672
680
* A route object represents a logical route, with (optionally) its child
@@ -700,7 +708,7 @@ export function generatePath(path: string, params: Params = {}): string {
700
708
return path
701
709
. replace ( / : ( \w + ) / g, ( _ , key ) => {
702
710
invariant ( params [ key ] != null , `Missing ":${ key } " param` ) ;
703
- return params [ key ] ;
711
+ return params [ key ] ! ;
704
712
} )
705
713
. replace ( / \/ * \* $ / , _ =>
706
714
params [ "*" ] == null ? "" : params [ "*" ] . replace ( / ^ \/ * / , "/" )
@@ -750,10 +758,10 @@ export function matchRoutes(
750
758
return matches ;
751
759
}
752
760
753
- export interface RouteMatch {
761
+ export interface RouteMatch < ParamKey extends string = string > {
754
762
route : RouteObject ;
755
763
pathname : string ;
756
- params : Params ;
764
+ params : Params < ParamKey > ;
757
765
}
758
766
759
767
function flattenRoutes (
@@ -861,13 +869,13 @@ function stableSort(array: any[], compareItems: (a: any, b: any) => number) {
861
869
array . sort ( ( a , b ) => compareItems ( a , b ) || copy . indexOf ( a ) - copy . indexOf ( b ) ) ;
862
870
}
863
871
864
- function matchRouteBranch (
872
+ function matchRouteBranch < ParamKey extends string = string > (
865
873
branch : RouteBranch ,
866
874
pathname : string
867
- ) : RouteMatch [ ] | null {
875
+ ) : RouteMatch < ParamKey > [ ] | null {
868
876
let routes = branch [ 1 ] ;
869
877
let matchedPathname = "/" ;
870
- let matchedParams : Params = { } ;
878
+ let matchedParams = { } as Params < ParamKey > ;
871
879
872
880
let matches : RouteMatch [ ] = [ ] ;
873
881
for ( let i = 0 ; i < routes . length ; ++ i ) {
@@ -893,7 +901,7 @@ function matchRouteBranch(
893
901
matches . push ( {
894
902
route,
895
903
pathname : matchedPathname ,
896
- params : readOnly < Params > ( matchedParams )
904
+ params : readOnly < Params < ParamKey > > ( matchedParams )
897
905
} ) ;
898
906
}
899
907
@@ -906,10 +914,10 @@ function matchRouteBranch(
906
914
*
907
915
* @see https://reactrouter.com/api/matchPath
908
916
*/
909
- export function matchPath (
917
+ export function matchPath < ParamKey extends string = string > (
910
918
pattern : PathPattern ,
911
919
pathname : string
912
- ) : PathMatch | null {
920
+ ) : PathMatch < ParamKey > | null {
913
921
if ( typeof pattern === "string" ) {
914
922
pattern = { path : pattern } ;
915
923
}
@@ -922,18 +930,24 @@ export function matchPath(
922
930
923
931
let matchedPathname = match [ 1 ] ;
924
932
let values = match . slice ( 2 ) ;
925
- let params = paramNames . reduce ( ( memo , paramName , index ) => {
926
- memo [ paramName ] = safelyDecodeURIComponent ( values [ index ] || "" , paramName ) ;
927
- return memo ;
928
- } , { } as Params ) ;
933
+ let params : Params = paramNames . reduce < Mutable < Params > > (
934
+ ( memo , paramName , index ) => {
935
+ memo [ paramName ] = safelyDecodeURIComponent (
936
+ values [ index ] || "" ,
937
+ paramName
938
+ ) ;
939
+ return memo ;
940
+ } ,
941
+ { }
942
+ ) ;
929
943
930
944
return { path, pathname : matchedPathname , params } ;
931
945
}
932
946
933
- export interface PathMatch {
947
+ export interface PathMatch < ParamKey extends string = string > {
934
948
path : string ;
935
949
pathname : string ;
936
- params : Params ;
950
+ params : Params < ParamKey > ;
937
951
}
938
952
939
953
function compilePath (
0 commit comments