Skip to content

Commit 25d5253

Browse files
authored
Fix types of encodeQueryParams and decodeQueryParams (#272)
1 parent 6e5cf4a commit 25d5253

File tree

9 files changed

+65
-42
lines changed

9 files changed

+65
-42
lines changed

packages/serialize-query-params/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ const CommaArrayParam = {
138138
decodeQueryParams<QPCMap extends QueryParamConfigMap>(
139139
paramConfigMap: QPCMap,
140140
encodedQuery: Partial<EncodedValueMap<QPCMap>>
141-
): Partial<DecodedValueMap<QPCMap>>
141+
): DecodedValueMap<QPCMap>
142142
```
143143

144144
Convert the values in query from strings to their natural types via the
@@ -170,7 +170,7 @@ const decodedQuery = decodeQueryParams(
170170
```js
171171
encodeQueryParams<QPCMap extends QueryParamConfigMap>(
172172
paramConfigMap: QPCMap,
173-
query: Partial<DecodedValueMap<QPCMap>>
173+
query: Partial<ToBeEncodedValueMap<QPCMap>>
174174
): Partial<EncodedValueMap<QPCMap>>
175175
```
176176

packages/serialize-query-params/src/decodeQueryParams.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@ import { DecodedValueMap, QueryParamConfigMap, EncodedValueMap } from './types';
55
* in paramConfigMap
66
*
77
* @param paramConfigMap Map from query name to { encode, decode } config
8-
* @param query Query updates mapping param name to decoded value
8+
* @param encodedQuery Query updates mapping param name to decoded value
99
*/
1010
export function decodeQueryParams<QPCMap extends QueryParamConfigMap>(
1111
paramConfigMap: QPCMap,
1212
encodedQuery: Partial<EncodedValueMap<QPCMap>>
13-
): Partial<DecodedValueMap<QPCMap>> {
13+
): DecodedValueMap<QPCMap> {
1414
const decodedQuery: Partial<DecodedValueMap<QPCMap>> = {};
1515

1616
// iterate over all keys in the config (#30)
@@ -39,9 +39,9 @@ export function decodeQueryParams<QPCMap extends QueryParamConfigMap>(
3939
} else {
4040
decodedQuery[paramName as keyof QPCMap] = paramConfigMap[
4141
paramName
42-
].decode(encodedValue as string | (string | null)[] | null);
42+
].decode(encodedValue);
4343
}
4444
}
4545

46-
return decodedQuery;
46+
return decodedQuery as DecodedValueMap<QPCMap>;
4747
}

packages/serialize-query-params/src/encodeQueryParams.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,27 @@
1-
import { DecodedValueMap, QueryParamConfigMap, EncodedValueMap } from './types';
1+
import {QueryParamConfigMap, EncodedValueMap, ToBeEncodedValueMap} from './types';
22

33
/**
44
* Convert the values in query to strings via the encode functions configured
55
* in paramConfigMap
66
*
77
* @param paramConfigMap Map from query name to { encode, decode } config
8-
* @param query Query updates mapping param name to decoded value
8+
* @param query Map from query name to value to be encoded
99
*/
1010
export function encodeQueryParams<QPCMap extends QueryParamConfigMap>(
1111
paramConfigMap: QPCMap,
12-
query: Partial<DecodedValueMap<QPCMap>>
12+
query: Partial<ToBeEncodedValueMap<QPCMap>>
1313
): Partial<EncodedValueMap<QPCMap>> {
1414
const encodedQuery: Partial<EncodedValueMap<QPCMap>> = {};
1515

1616
const paramNames = Object.keys(query);
1717
for (const paramName of paramNames) {
18-
const decodedValue = query[paramName];
18+
const valueToBeEncoded = query[paramName];
1919

2020
if (!paramConfigMap[paramName]) {
2121
// NOTE: we could just not encode it, but it is probably convenient to have
2222
// it be included by default as a string type.
2323
(encodedQuery as any)[paramName] =
24-
decodedValue == null ? decodedValue : String(decodedValue);
24+
valueToBeEncoded == null ? valueToBeEncoded : String(valueToBeEncoded);
2525
} else {
2626
encodedQuery[paramName as keyof QPCMap] = paramConfigMap[
2727
paramName

packages/serialize-query-params/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ export type {
5454
QueryParamConfigMap,
5555
DecodedValueMap,
5656
EncodedValueMap,
57+
ToBeEncodedValueMap
5758
} from './types';
5859

5960
export {

packages/serialize-query-params/src/serialize.ts

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1+
import {EncodedValue} from "types";
2+
13
/**
24
* Interprets an encoded string and returns either the string or null/undefined if not available.
35
* Ignores array inputs (takes just first element in array)
46
* @param input encoded string
57
*/
68
function getEncodedValue(
7-
input: string | (string | null)[] | null | undefined,
9+
input: EncodedValue,
810
allowEmptyString?: boolean
911
): string | null | undefined {
1012
if (input == null) {
@@ -35,7 +37,7 @@ function getEncodedValue(
3537
* @param input encoded string
3638
*/
3739
function getEncodedValueArray(
38-
input: string | (string | null)[] | null | undefined
40+
input: EncodedValue
3941
): (string | null)[] | null | undefined {
4042
if (input == null) {
4143
return input;
@@ -78,7 +80,7 @@ export function encodeDate(
7880
* @return {Date} parsed date
7981
*/
8082
export function decodeDate(
81-
input: string | (string | null)[] | null | undefined
83+
input: EncodedValue
8284
): Date | null | undefined {
8385
const dateString = getEncodedValue(input);
8486
if (dateString == null) return dateString;
@@ -130,7 +132,7 @@ export function encodeDateTime(
130132
* @return {Date} parsed date
131133
*/
132134
export function decodeDateTime(
133-
input: string | (string | null)[] | null | undefined
135+
input: EncodedValue
134136
): Date | null | undefined {
135137
const dateString = getEncodedValue(input);
136138
if (dateString == null) return dateString;
@@ -170,7 +172,7 @@ export function encodeBoolean(
170172
* @return {Boolean} the boolean value
171173
*/
172174
export function decodeBoolean(
173-
input: string | (string | null)[] | null | undefined
175+
input: EncodedValue
174176
): boolean | null | undefined {
175177
const boolStr = getEncodedValue(input);
176178
if (boolStr == null) return boolStr;
@@ -210,7 +212,7 @@ export function encodeNumber(
210212
* @return {Number} the number value
211213
*/
212214
export function decodeNumber(
213-
input: string | (string | null)[] | null | undefined
215+
input: EncodedValue
214216
): number | null | undefined {
215217
const numStr = getEncodedValue(input);
216218
if (numStr == null) return numStr;
@@ -227,7 +229,7 @@ export function decodeNumber(
227229
* @return {String} the encoded string
228230
*/
229231
export function encodeString(
230-
str: string | (string | null)[] | null | undefined
232+
str: EncodedValue
231233
): string | null | undefined {
232234
if (str == null) {
233235
return str;
@@ -245,7 +247,7 @@ export function encodeString(
245247
* @return {String} the string value
246248
*/
247249
export function decodeString(
248-
input: string | (string | null)[] | null | undefined
250+
input: EncodedValue
249251
): string | null | undefined {
250252
const str = getEncodedValue(input, true);
251253
if (str == null) return str;
@@ -263,7 +265,7 @@ export function decodeString(
263265
* @return {String} the string value from enumValues
264266
*/
265267
export function decodeEnum<T extends string>(
266-
input: string | (string | null)[] | null | undefined,
268+
input: EncodedValue,
267269
enumValues: T[]
268270
): T | null | undefined {
269271
const str = decodeString(input);
@@ -280,7 +282,7 @@ export function decodeEnum<T extends string>(
280282
* @return {T[]} the string value from enumValues
281283
*/
282284
export function decodeArrayEnum<T extends string>(
283-
input: string | (string | null)[] | null | undefined,
285+
input: EncodedValue,
284286
enumValues: T[]
285287
): T[] | null | undefined {
286288
const arr = decodeArray(input);
@@ -302,7 +304,7 @@ export function decodeArrayEnum<T extends string>(
302304
* @return {T[]} the string value from enumValues
303305
*/
304306
export function decodeDelimitedArrayEnum<T extends string>(
305-
input: string | (string | null)[] | null | undefined,
307+
input: EncodedValue,
306308
enumValues: T[],
307309
entrySeparator = '_'
308310
): T[] | null | undefined {
@@ -336,7 +338,7 @@ export function encodeJson(
336338
* @return {Any} The javascript representation
337339
*/
338340
export function decodeJson(
339-
input: string | (string | null)[] | null | undefined
341+
input: EncodedValue
340342
): any | null | undefined {
341343
const jsonStr = getEncodedValue(input);
342344
if (jsonStr == null) return jsonStr;
@@ -376,7 +378,7 @@ export function encodeArray(
376378
* @return {Array} The javascript representation
377379
*/
378380
export function decodeArray(
379-
input: string | (string | null)[] | null | undefined
381+
input: EncodedValue
380382
): (string | null)[] | null | undefined {
381383
const arr = getEncodedValueArray(input);
382384
if (arr == null) return arr;
@@ -409,7 +411,7 @@ export function encodeNumericArray(
409411
* @return {Array} The javascript representation
410412
*/
411413
export function decodeNumericArray(
412-
input: string | (string | null)[] | null | undefined
414+
input: EncodedValue
413415
): (number | null)[] | null | undefined {
414416
const arr = decodeArray(input);
415417
if (arr == null) return arr;
@@ -449,7 +451,7 @@ export function encodeDelimitedArray(
449451
* @return {Array} The javascript representation
450452
*/
451453
export function decodeDelimitedArray(
452-
input: string | (string | null)[] | null | undefined,
454+
input: EncodedValue,
453455
entrySeparator = '_'
454456
): (string | null)[] | null | undefined {
455457
const arrayStr = getEncodedValue(input, true);
@@ -481,7 +483,7 @@ export const encodeDelimitedNumericArray = encodeDelimitedArray as (
481483
* @return {Array} The javascript representation
482484
*/
483485
export function decodeDelimitedNumericArray(
484-
arrayStr: string | (string | null)[] | null | undefined,
486+
arrayStr: EncodedValue,
485487
entrySeparator = '_'
486488
): (number | null)[] | null | undefined {
487489
const decoded = decodeDelimitedArray(arrayStr, entrySeparator);
@@ -528,7 +530,7 @@ export function encodeObject(
528530
* @return {Object} The javascript object
529531
*/
530532
export function decodeObject(
531-
input: string | (string | null)[] | null | undefined,
533+
input: EncodedValue,
532534
keyValSeparator = '-',
533535
entrySeparator = '_'
534536
): { [key: string]: string } | null | undefined {
@@ -577,7 +579,7 @@ export const encodeNumericObject = encodeObject as (
577579
* @return {Object} The javascript object
578580
*/
579581
export function decodeNumericObject(
580-
input: string | (string | null)[] | null | undefined,
582+
input: EncodedValue,
581583
keyValSeparator = '-',
582584
entrySeparator = '_'
583585
): { [key: string]: number | null | undefined } | null | undefined {

packages/serialize-query-params/src/types.ts

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
1+
/**
2+
* Encoded query parameter's value
3+
*/
4+
export type EncodedValue = string | (string | null)[] | null | undefined;
5+
16
/**
27
* Encoded query parameters, possibly including null or undefined values
38
*/
49
export interface EncodedQuery {
5-
[key: string]: string | (string | null)[] | null | undefined;
10+
[key: string]: EncodedValue;
611
}
712

813
/**
@@ -15,10 +20,10 @@ export interface EncodedQuery {
1520
*/
1621
export interface QueryParamConfig<D, D2 = D> {
1722
/** Convert the query param value to a string */
18-
encode: (value: D) => string | (string | null)[] | null | undefined;
23+
encode: (value: D) => EncodedValue;
1924

2025
/** Convert the query param string value to its native type */
21-
decode: (value: string | (string | null)[] | null | undefined) => D2;
26+
decode: (value: EncodedValue) => D2;
2227

2328
/** Checks if two values are equal (otherwise typically shallowEqual will be used) */
2429
equals?: (valueA: D | D2, valueB: D | D2) => boolean;
@@ -60,5 +65,12 @@ export type DecodedValueMap<QPCMap extends QueryParamConfigMap> = {
6065
* Mapping from a query parameter name to it's encoded value type
6166
*/
6267
export type EncodedValueMap<QPCMap extends QueryParamConfigMap> = {
63-
[P in keyof QPCMap]: string | (string | null)[] | null | undefined;
68+
[P in keyof QPCMap]: EncodedValue;
69+
};
70+
71+
/**
72+
* Mapping from a query parameter name to it's value to be encoded
73+
*/
74+
export type ToBeEncodedValueMap<QPCMap extends QueryParamConfigMap> = {
75+
[P in keyof QPCMap]: Parameters<QPCMap[P]['encode']>[0];
6476
};

packages/use-query-params/README.md

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -386,8 +386,14 @@ const CommaArrayParam = {
386386
#### useQueryParam
387387

388388
```js
389-
useQueryParam<T>(name: string, paramConfig?: QueryParamConfig<T>, options?: QueryParamOptions):
390-
[T | undefined, (newValue: T, updateType?: UrlUpdateType) => void]
389+
useQueryParam<TypeToEncode, TypeFromDecode = TypeToEncode>(
390+
name: string,
391+
paramConfig?: QueryParamConfig<TypeToEncode, TypeFromDecode>,
392+
options?: QueryParamOptions
393+
): [
394+
TypeFromDecode,
395+
(newValue: NewValueType<TypeToEncode>, updateType?: UrlUpdateType) => void
396+
]
391397
```
392398

393399
Given a query param name and query parameter configuration `{ encode, decode }`
@@ -551,8 +557,8 @@ is one of `'pushIn' | 'push' | 'replaceIn' | 'replace'`, defaulting to
551557
```js
552558
encodeQueryParams<QPCMap extends QueryParamConfigMap>(
553559
paramConfigMap: QPCMap,
554-
query: Partial<DecodedValueMap<QPCMap>>
555-
): EncodedQueryWithNulls
560+
query: Partial<ToBeEncodedValueMap<QPCMap>>
561+
): Partial<EncodedValueMap<QPCMap>>
556562
```
557563

558564
Convert the values in query to strings via the encode functions configured

packages/use-query-params/src/types.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import {
22
QueryParamConfigMap,
33
DecodedValueMap,
44
QueryParamConfig,
5+
ToBeEncodedValueMap,
56
} from 'serialize-query-params';
67

78
/**
@@ -19,10 +20,10 @@ export type UrlUpdateType = 'replace' | 'replaceIn' | 'push' | 'pushIn';
1920
*/
2021
export type SetQuery<QPCMap extends QueryParamConfigMap> = (
2122
changes:
22-
| Partial<DecodedValueMap<QPCMap>>
23+
| Partial<ToBeEncodedValueMap<QPCMap>>
2324
| ((
2425
latestValues: DecodedValueMap<QPCMap>
25-
) => Partial<DecodedValueMap<QPCMap>>),
26+
) => Partial<ToBeEncodedValueMap<QPCMap>>),
2627
updateType?: UrlUpdateType
2728
) => void;
2829

packages/use-query-params/src/useQueryParams.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { useEffect, useMemo, useRef, useState } from 'react';
22
import {
3+
ToBeEncodedValueMap,
34
DecodedValueMap,
45
QueryParamConfig,
56
QueryParamConfigMap,
@@ -23,9 +24,9 @@ import { enqueueUpdate } from './updateSearchString';
2324
import { serializeUrlNameMap } from './urlName';
2425

2526
// for multiple param config
26-
type ChangesType<DecodedValueMapType> =
27-
| Partial<DecodedValueMapType>
28-
| ((latestValues: DecodedValueMapType) => Partial<DecodedValueMapType>);
27+
type ChangesType<QPCMap extends QueryParamConfigMap> =
28+
| Partial<ToBeEncodedValueMap<QPCMap>>
29+
| ((latestValues: DecodedValueMap<QPCMap>) => Partial<ToBeEncodedValueMap<QPCMap>>);
2930

3031
type UseQueryParamsResult<QPCMap extends QueryParamConfigMap> = [
3132
DecodedValueMap<QPCMap>,

0 commit comments

Comments
 (0)