Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix types of encodeQueryParams and decodeQueryParams #272

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/serialize-query-params/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ const CommaArrayParam = {
decodeQueryParams<QPCMap extends QueryParamConfigMap>(
paramConfigMap: QPCMap,
encodedQuery: Partial<EncodedValueMap<QPCMap>>
): Partial<DecodedValueMap<QPCMap>>
): DecodedValueMap<QPCMap>
```

Convert the values in query from strings to their natural types via the
Expand Down Expand Up @@ -170,7 +170,7 @@ const decodedQuery = decodeQueryParams(
```js
encodeQueryParams<QPCMap extends QueryParamConfigMap>(
paramConfigMap: QPCMap,
query: Partial<DecodedValueMap<QPCMap>>
query: Partial<ToBeEncodedValueMap<QPCMap>>
): Partial<EncodedValueMap<QPCMap>>
```

Expand Down
8 changes: 4 additions & 4 deletions packages/serialize-query-params/src/decodeQueryParams.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ import { DecodedValueMap, QueryParamConfigMap, EncodedValueMap } from './types';
* in paramConfigMap
*
* @param paramConfigMap Map from query name to { encode, decode } config
* @param query Query updates mapping param name to decoded value
* @param encodedQuery Query updates mapping param name to decoded value
*/
export function decodeQueryParams<QPCMap extends QueryParamConfigMap>(
paramConfigMap: QPCMap,
encodedQuery: Partial<EncodedValueMap<QPCMap>>
): Partial<DecodedValueMap<QPCMap>> {
): DecodedValueMap<QPCMap> {
const decodedQuery: Partial<DecodedValueMap<QPCMap>> = {};

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

return decodedQuery;
return decodedQuery as DecodedValueMap<QPCMap>;
}
10 changes: 5 additions & 5 deletions packages/serialize-query-params/src/encodeQueryParams.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
import { DecodedValueMap, QueryParamConfigMap, EncodedValueMap } from './types';
import {QueryParamConfigMap, EncodedValueMap, ToBeEncodedValueMap} from './types';

/**
* Convert the values in query to strings via the encode functions configured
* in paramConfigMap
*
* @param paramConfigMap Map from query name to { encode, decode } config
* @param query Query updates mapping param name to decoded value
* @param query Map from query name to value to be encoded
*/
export function encodeQueryParams<QPCMap extends QueryParamConfigMap>(
paramConfigMap: QPCMap,
query: Partial<DecodedValueMap<QPCMap>>
query: Partial<ToBeEncodedValueMap<QPCMap>>
): Partial<EncodedValueMap<QPCMap>> {
const encodedQuery: Partial<EncodedValueMap<QPCMap>> = {};

const paramNames = Object.keys(query);
for (const paramName of paramNames) {
const decodedValue = query[paramName];
const valueToBeEncoded = query[paramName];

if (!paramConfigMap[paramName]) {
// NOTE: we could just not encode it, but it is probably convenient to have
// it be included by default as a string type.
(encodedQuery as any)[paramName] =
decodedValue == null ? decodedValue : String(decodedValue);
valueToBeEncoded == null ? valueToBeEncoded : String(valueToBeEncoded);
} else {
encodedQuery[paramName as keyof QPCMap] = paramConfigMap[
paramName
Expand Down
1 change: 1 addition & 0 deletions packages/serialize-query-params/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ export type {
QueryParamConfigMap,
DecodedValueMap,
EncodedValueMap,
ToBeEncodedValueMap
} from './types';

export {
Expand Down
38 changes: 20 additions & 18 deletions packages/serialize-query-params/src/serialize.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import {EncodedValue} from "types";

/**
* Interprets an encoded string and returns either the string or null/undefined if not available.
* Ignores array inputs (takes just first element in array)
* @param input encoded string
*/
function getEncodedValue(
input: string | (string | null)[] | null | undefined,
input: EncodedValue,
allowEmptyString?: boolean
): string | null | undefined {
if (input == null) {
Expand Down Expand Up @@ -35,7 +37,7 @@ function getEncodedValue(
* @param input encoded string
*/
function getEncodedValueArray(
input: string | (string | null)[] | null | undefined
input: EncodedValue
): (string | null)[] | null | undefined {
if (input == null) {
return input;
Expand Down Expand Up @@ -78,7 +80,7 @@ export function encodeDate(
* @return {Date} parsed date
*/
export function decodeDate(
input: string | (string | null)[] | null | undefined
input: EncodedValue
): Date | null | undefined {
const dateString = getEncodedValue(input);
if (dateString == null) return dateString;
Expand Down Expand Up @@ -130,7 +132,7 @@ export function encodeDateTime(
* @return {Date} parsed date
*/
export function decodeDateTime(
input: string | (string | null)[] | null | undefined
input: EncodedValue
): Date | null | undefined {
const dateString = getEncodedValue(input);
if (dateString == null) return dateString;
Expand Down Expand Up @@ -170,7 +172,7 @@ export function encodeBoolean(
* @return {Boolean} the boolean value
*/
export function decodeBoolean(
input: string | (string | null)[] | null | undefined
input: EncodedValue
): boolean | null | undefined {
const boolStr = getEncodedValue(input);
if (boolStr == null) return boolStr;
Expand Down Expand Up @@ -210,7 +212,7 @@ export function encodeNumber(
* @return {Number} the number value
*/
export function decodeNumber(
input: string | (string | null)[] | null | undefined
input: EncodedValue
): number | null | undefined {
const numStr = getEncodedValue(input);
if (numStr == null) return numStr;
Expand All @@ -227,7 +229,7 @@ export function decodeNumber(
* @return {String} the encoded string
*/
export function encodeString(
str: string | (string | null)[] | null | undefined
str: EncodedValue
): string | null | undefined {
if (str == null) {
return str;
Expand All @@ -245,7 +247,7 @@ export function encodeString(
* @return {String} the string value
*/
export function decodeString(
input: string | (string | null)[] | null | undefined
input: EncodedValue
): string | null | undefined {
const str = getEncodedValue(input, true);
if (str == null) return str;
Expand All @@ -263,7 +265,7 @@ export function decodeString(
* @return {String} the string value from enumValues
*/
export function decodeEnum<T extends string>(
input: string | (string | null)[] | null | undefined,
input: EncodedValue,
enumValues: T[]
): T | null | undefined {
const str = decodeString(input);
Expand All @@ -280,7 +282,7 @@ export function decodeEnum<T extends string>(
* @return {T[]} the string value from enumValues
*/
export function decodeArrayEnum<T extends string>(
input: string | (string | null)[] | null | undefined,
input: EncodedValue,
enumValues: T[]
): T[] | null | undefined {
const arr = decodeArray(input);
Expand All @@ -302,7 +304,7 @@ export function decodeArrayEnum<T extends string>(
* @return {T[]} the string value from enumValues
*/
export function decodeDelimitedArrayEnum<T extends string>(
input: string | (string | null)[] | null | undefined,
input: EncodedValue,
enumValues: T[],
entrySeparator = '_'
): T[] | null | undefined {
Expand Down Expand Up @@ -336,7 +338,7 @@ export function encodeJson(
* @return {Any} The javascript representation
*/
export function decodeJson(
input: string | (string | null)[] | null | undefined
input: EncodedValue
): any | null | undefined {
const jsonStr = getEncodedValue(input);
if (jsonStr == null) return jsonStr;
Expand Down Expand Up @@ -376,7 +378,7 @@ export function encodeArray(
* @return {Array} The javascript representation
*/
export function decodeArray(
input: string | (string | null)[] | null | undefined
input: EncodedValue
): (string | null)[] | null | undefined {
const arr = getEncodedValueArray(input);
if (arr == null) return arr;
Expand Down Expand Up @@ -409,7 +411,7 @@ export function encodeNumericArray(
* @return {Array} The javascript representation
*/
export function decodeNumericArray(
input: string | (string | null)[] | null | undefined
input: EncodedValue
): (number | null)[] | null | undefined {
const arr = decodeArray(input);
if (arr == null) return arr;
Expand Down Expand Up @@ -449,7 +451,7 @@ export function encodeDelimitedArray(
* @return {Array} The javascript representation
*/
export function decodeDelimitedArray(
input: string | (string | null)[] | null | undefined,
input: EncodedValue,
entrySeparator = '_'
): (string | null)[] | null | undefined {
const arrayStr = getEncodedValue(input, true);
Expand Down Expand Up @@ -481,7 +483,7 @@ export const encodeDelimitedNumericArray = encodeDelimitedArray as (
* @return {Array} The javascript representation
*/
export function decodeDelimitedNumericArray(
arrayStr: string | (string | null)[] | null | undefined,
arrayStr: EncodedValue,
entrySeparator = '_'
): (number | null)[] | null | undefined {
const decoded = decodeDelimitedArray(arrayStr, entrySeparator);
Expand Down Expand Up @@ -528,7 +530,7 @@ export function encodeObject(
* @return {Object} The javascript object
*/
export function decodeObject(
input: string | (string | null)[] | null | undefined,
input: EncodedValue,
keyValSeparator = '-',
entrySeparator = '_'
): { [key: string]: string } | null | undefined {
Expand Down Expand Up @@ -577,7 +579,7 @@ export const encodeNumericObject = encodeObject as (
* @return {Object} The javascript object
*/
export function decodeNumericObject(
input: string | (string | null)[] | null | undefined,
input: EncodedValue,
keyValSeparator = '-',
entrySeparator = '_'
): { [key: string]: number | null | undefined } | null | undefined {
Expand Down
20 changes: 16 additions & 4 deletions packages/serialize-query-params/src/types.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
/**
* Encoded query parameter's value
*/
export type EncodedValue = string | (string | null)[] | null | undefined;

/**
* Encoded query parameters, possibly including null or undefined values
*/
export interface EncodedQuery {
[key: string]: string | (string | null)[] | null | undefined;
[key: string]: EncodedValue;
}

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

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

/** Checks if two values are equal (otherwise typically shallowEqual will be used) */
equals?: (valueA: D | D2, valueB: D | D2) => boolean;
Expand Down Expand Up @@ -60,5 +65,12 @@ export type DecodedValueMap<QPCMap extends QueryParamConfigMap> = {
* Mapping from a query parameter name to it's encoded value type
*/
export type EncodedValueMap<QPCMap extends QueryParamConfigMap> = {
[P in keyof QPCMap]: string | (string | null)[] | null | undefined;
[P in keyof QPCMap]: EncodedValue;
};

/**
* Mapping from a query parameter name to it's value to be encoded
*/
export type ToBeEncodedValueMap<QPCMap extends QueryParamConfigMap> = {
[P in keyof QPCMap]: Parameters<QPCMap[P]['encode']>[0];
};
14 changes: 10 additions & 4 deletions packages/use-query-params/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -386,8 +386,14 @@ const CommaArrayParam = {
#### useQueryParam

```js
useQueryParam<T>(name: string, paramConfig?: QueryParamConfig<T>, options?: QueryParamOptions):
[T | undefined, (newValue: T, updateType?: UrlUpdateType) => void]
useQueryParam<TypeToEncode, TypeFromDecode = TypeToEncode>(
name: string,
paramConfig?: QueryParamConfig<TypeToEncode, TypeFromDecode>,
options?: QueryParamOptions
): [
TypeFromDecode,
(newValue: NewValueType<TypeToEncode>, updateType?: UrlUpdateType) => void
]
```

Given a query param name and query parameter configuration `{ encode, decode }`
Expand Down Expand Up @@ -551,8 +557,8 @@ is one of `'pushIn' | 'push' | 'replaceIn' | 'replace'`, defaulting to
```js
encodeQueryParams<QPCMap extends QueryParamConfigMap>(
paramConfigMap: QPCMap,
query: Partial<DecodedValueMap<QPCMap>>
): EncodedQueryWithNulls
query: Partial<ToBeEncodedValueMap<QPCMap>>
): Partial<EncodedValueMap<QPCMap>>
```

Convert the values in query to strings via the encode functions configured
Expand Down
5 changes: 3 additions & 2 deletions packages/use-query-params/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
QueryParamConfigMap,
DecodedValueMap,
QueryParamConfig,
ToBeEncodedValueMap,
} from 'serialize-query-params';

/**
Expand All @@ -19,10 +20,10 @@ export type UrlUpdateType = 'replace' | 'replaceIn' | 'push' | 'pushIn';
*/
export type SetQuery<QPCMap extends QueryParamConfigMap> = (
changes:
| Partial<DecodedValueMap<QPCMap>>
| Partial<ToBeEncodedValueMap<QPCMap>>
| ((
latestValues: DecodedValueMap<QPCMap>
) => Partial<DecodedValueMap<QPCMap>>),
) => Partial<ToBeEncodedValueMap<QPCMap>>),
updateType?: UrlUpdateType
) => void;

Expand Down
7 changes: 4 additions & 3 deletions packages/use-query-params/src/useQueryParams.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useEffect, useMemo, useRef, useState } from 'react';
import {
ToBeEncodedValueMap,
DecodedValueMap,
QueryParamConfig,
QueryParamConfigMap,
Expand All @@ -23,9 +24,9 @@ import { enqueueUpdate } from './updateSearchString';
import { serializeUrlNameMap } from './urlName';

// for multiple param config
type ChangesType<DecodedValueMapType> =
| Partial<DecodedValueMapType>
| ((latestValues: DecodedValueMapType) => Partial<DecodedValueMapType>);
type ChangesType<QPCMap extends QueryParamConfigMap> =
| Partial<ToBeEncodedValueMap<QPCMap>>
| ((latestValues: DecodedValueMap<QPCMap>) => Partial<ToBeEncodedValueMap<QPCMap>>);

type UseQueryParamsResult<QPCMap extends QueryParamConfigMap> = [
DecodedValueMap<QPCMap>,
Expand Down