Skip to content

Commit 8715b21

Browse files
committed
feat: make defineParamParser() more intuitive
Now it takes a single type param that defines what the param becomes. I find this to be more intuitive than the previous version: ```ts export const parser = defineParamParser<number>({ get: value => { if (value == null) return null if (Array.isArray(value)) { return value .filter(v => v != null) .map(Number) .filter(v => !Number.isNaN(v)) } return Number.isNaN(Number(value)) ? miss(`"${value}" is not a valid number`) : Number(value) }, set: value => Array.isArray(value) ? value.map(String) : value == null ? null : String(value), }) ```
1 parent 8d3e60e commit 8715b21

2 files changed

Lines changed: 60 additions & 11 deletions

File tree

  • packages/router/src/experimental/route-resolver/matchers/param-parsers

packages/router/src/experimental/route-resolver/matchers/param-parsers/index.ts

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,9 @@ export function definePathParamParser<
4848
TParam,
4949
// path params are parsed by the router as these
5050
// we use extend to allow infering a more specific type
51-
TUrlParam extends string | string[] | null,
51+
TUrlParam extends string | string[] | null = string | string[] | null,
5252
// we can allow pushing with extra values
53-
TParamRaw,
53+
TParamRaw = TParam,
5454
>(parser: Required<ParamParser<TParam, TUrlParam, TParamRaw>>) {
5555
return parser
5656
}
@@ -74,10 +74,54 @@ export function defineQueryParamParser<
7474
}
7575

7676
/**
77-
* Alias for {@link defineQueryParamParser}. Implementing a param parser like this
78-
* works for path, query, and hash params.
77+
* Defines a param parser that works with any kind of param (path, repeatable, optional, query, hash, ...)
78+
*
79+
* @example
80+
*
81+
* Here is an example that allows arbitrary numbers (NaN values are filtered
82+
* out). It supports repeatable params, so it can be used both as a path param
83+
* parser and a query param parser.
84+
*
85+
* ```ts
86+
* export const parser = defineParamParser<number>({
87+
* get: value => {
88+
* if (value == null) return null
89+
* if (Array.isArray(value)) {
90+
* return value
91+
* .filter(v => v != null)
92+
* .map(Number)
93+
* .filter(v => !Number.isNaN(v))
94+
* }
95+
*
96+
* return Number.isNaN(Number(value))
97+
* ? miss(`"${value}" is not a valid number`)
98+
* : Number(value)
99+
* },
100+
*
101+
* set: value =>
102+
* Array.isArray(value)
103+
* ? value.map(String)
104+
* : value == null
105+
* ? null
106+
* : String(value),
107+
* })
108+
* ```
79109
*
80110
* @see {@link defineQueryParamParser}
81111
* @see {@link definePathParamParser}
82112
*/
83-
export const defineParamParser = defineQueryParamParser
113+
export function defineParamParser<
114+
TParam,
115+
// we can allow pushing with extra values
116+
TParamRaw = TParam,
117+
>(
118+
parser: Required<
119+
ParamParser<
120+
TParam | TParam[] | null,
121+
MatcherQueryParamsValue,
122+
TParamRaw | TParamRaw[] | null
123+
>
124+
>
125+
) {
126+
return parser
127+
}

packages/router/src/experimental/route-resolver/matchers/param-parsers/types.ts

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,22 @@ import type { MatcherQueryParamsValue } from '../matcher-pattern'
44
* Defines a parser that can read a param from the url (string-based) and
55
* transform it into a more complex type, or vice versa.
66
*
7+
* @param TParam - the type of the param after parsing as exposed in `route.params`
8+
* @param TUrlParam - this is the most permissive type that can be passed to
9+
* get and returned by set. By default it's the type of query path params
10+
* (stricter as they do not allow `null` within an array or `undefined`)
11+
* @param TParamRaw - the type that can be passed as a location when
12+
* navigating: `router.push({ params: {}})` it's sometimes more permissive than
13+
* TParam, for example allowing nullish values
14+
*
715
* @see MatcherPattern
816
*/
917
export interface ParamParser<
10-
// type of the param after parsing as exposed in `route.params`
18+
// the final type in route.params
1119
TParam = MatcherQueryParamsValue,
12-
// this is the most permissive type that can be passed to get and returned by
13-
// set. By default it's the type of query path params (stricter as they do
14-
// not allow `null` within an array or `undefined`)
20+
// what gets passed to `get`
1521
TUrlParam = MatcherQueryParamsValue,
16-
// the type that can be passed as a location when navigating: `router.push({ params: { }})`
17-
// it's sometimes more permissive than TParam, for example allowing nullish values
22+
// a potentially more permissive type
1823
TParamRaw = TParam,
1924
> {
2025
get?: (value: NoInfer<TUrlParam>) => TParam

0 commit comments

Comments
 (0)