From 050d69476e1b6d830c784cd0b0db0018596fcf85 Mon Sep 17 00:00:00 2001 From: Dmitry Zhavoronkov Date: Fri, 14 Jul 2023 18:48:10 +0700 Subject: [PATCH] Fix types of encodeQueryParams and decodeQueryParams --- packages/serialize-query-params/README.md | 4 +- .../src/decodeQueryParams.ts | 8 ++-- .../src/encodeQueryParams.ts | 10 ++--- packages/serialize-query-params/src/index.ts | 1 + .../serialize-query-params/src/serialize.ts | 38 ++++++++++--------- packages/serialize-query-params/src/types.ts | 20 ++++++++-- packages/use-query-params/README.md | 14 +++++-- packages/use-query-params/src/types.ts | 5 ++- .../use-query-params/src/useQueryParams.ts | 7 ++-- 9 files changed, 65 insertions(+), 42 deletions(-) diff --git a/packages/serialize-query-params/README.md b/packages/serialize-query-params/README.md index 46a7f61..17f1545 100644 --- a/packages/serialize-query-params/README.md +++ b/packages/serialize-query-params/README.md @@ -138,7 +138,7 @@ const CommaArrayParam = { decodeQueryParams( paramConfigMap: QPCMap, encodedQuery: Partial> -): Partial> +): DecodedValueMap ``` Convert the values in query from strings to their natural types via the @@ -170,7 +170,7 @@ const decodedQuery = decodeQueryParams( ```js encodeQueryParams( paramConfigMap: QPCMap, - query: Partial> + query: Partial> ): Partial> ``` diff --git a/packages/serialize-query-params/src/decodeQueryParams.ts b/packages/serialize-query-params/src/decodeQueryParams.ts index 7bf2b6d..f14b57a 100644 --- a/packages/serialize-query-params/src/decodeQueryParams.ts +++ b/packages/serialize-query-params/src/decodeQueryParams.ts @@ -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( paramConfigMap: QPCMap, encodedQuery: Partial> -): Partial> { +): DecodedValueMap { const decodedQuery: Partial> = {}; // iterate over all keys in the config (#30) @@ -39,9 +39,9 @@ export function decodeQueryParams( } else { decodedQuery[paramName as keyof QPCMap] = paramConfigMap[ paramName - ].decode(encodedValue as string | (string | null)[] | null); + ].decode(encodedValue); } } - return decodedQuery; + return decodedQuery as DecodedValueMap; } diff --git a/packages/serialize-query-params/src/encodeQueryParams.ts b/packages/serialize-query-params/src/encodeQueryParams.ts index cd0f777..eabb974 100644 --- a/packages/serialize-query-params/src/encodeQueryParams.ts +++ b/packages/serialize-query-params/src/encodeQueryParams.ts @@ -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( paramConfigMap: QPCMap, - query: Partial> + query: Partial> ): Partial> { const encodedQuery: Partial> = {}; 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 diff --git a/packages/serialize-query-params/src/index.ts b/packages/serialize-query-params/src/index.ts index 19b5811..692b0fe 100644 --- a/packages/serialize-query-params/src/index.ts +++ b/packages/serialize-query-params/src/index.ts @@ -52,6 +52,7 @@ export type { QueryParamConfigMap, DecodedValueMap, EncodedValueMap, + ToBeEncodedValueMap } from './types'; export { diff --git a/packages/serialize-query-params/src/serialize.ts b/packages/serialize-query-params/src/serialize.ts index 55c4cae..a521671 100644 --- a/packages/serialize-query-params/src/serialize.ts +++ b/packages/serialize-query-params/src/serialize.ts @@ -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) { @@ -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; @@ -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; @@ -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; @@ -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; @@ -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; @@ -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; @@ -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; @@ -263,7 +265,7 @@ export function decodeString( * @return {String} the string value from enumValues */ export function decodeEnum( - input: string | (string | null)[] | null | undefined, + input: EncodedValue, enumValues: T[] ): T | null | undefined { const str = decodeString(input); @@ -280,7 +282,7 @@ export function decodeEnum( * @return {T[]} the string value from enumValues */ export function decodeArrayEnum( - input: string | (string | null)[] | null | undefined, + input: EncodedValue, enumValues: T[] ): T[] | null | undefined { const arr = decodeArray(input); @@ -302,7 +304,7 @@ export function decodeArrayEnum( * @return {T[]} the string value from enumValues */ export function decodeDelimitedArrayEnum( - input: string | (string | null)[] | null | undefined, + input: EncodedValue, enumValues: T[], entrySeparator = '_' ): T[] | null | undefined { @@ -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; @@ -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; @@ -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; @@ -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); @@ -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); @@ -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 { @@ -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 { diff --git a/packages/serialize-query-params/src/types.ts b/packages/serialize-query-params/src/types.ts index 4beb5bf..f9827df 100644 --- a/packages/serialize-query-params/src/types.ts +++ b/packages/serialize-query-params/src/types.ts @@ -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; } /** @@ -15,10 +20,10 @@ export interface EncodedQuery { */ export interface QueryParamConfig { /** 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; @@ -60,5 +65,12 @@ export type DecodedValueMap = { * Mapping from a query parameter name to it's encoded value type */ export type EncodedValueMap = { - [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 = { + [P in keyof QPCMap]: Parameters[0]; }; diff --git a/packages/use-query-params/README.md b/packages/use-query-params/README.md index 9f2a1b7..c05750c 100644 --- a/packages/use-query-params/README.md +++ b/packages/use-query-params/README.md @@ -386,8 +386,14 @@ const CommaArrayParam = { #### useQueryParam ```js -useQueryParam(name: string, paramConfig?: QueryParamConfig, options?: QueryParamOptions): - [T | undefined, (newValue: T, updateType?: UrlUpdateType) => void] +useQueryParam( + name: string, + paramConfig?: QueryParamConfig, + options?: QueryParamOptions +): [ + TypeFromDecode, + (newValue: NewValueType, updateType?: UrlUpdateType) => void +] ``` Given a query param name and query parameter configuration `{ encode, decode }` @@ -551,8 +557,8 @@ is one of `'pushIn' | 'push' | 'replaceIn' | 'replace'`, defaulting to ```js encodeQueryParams( paramConfigMap: QPCMap, - query: Partial> -): EncodedQueryWithNulls + query: Partial> +): Partial> ``` Convert the values in query to strings via the encode functions configured diff --git a/packages/use-query-params/src/types.ts b/packages/use-query-params/src/types.ts index 6ed4676..afedd0c 100644 --- a/packages/use-query-params/src/types.ts +++ b/packages/use-query-params/src/types.ts @@ -2,6 +2,7 @@ import { QueryParamConfigMap, DecodedValueMap, QueryParamConfig, + ToBeEncodedValueMap, } from 'serialize-query-params'; /** @@ -19,10 +20,10 @@ export type UrlUpdateType = 'replace' | 'replaceIn' | 'push' | 'pushIn'; */ export type SetQuery = ( changes: - | Partial> + | Partial> | (( latestValues: DecodedValueMap - ) => Partial>), + ) => Partial>), updateType?: UrlUpdateType ) => void; diff --git a/packages/use-query-params/src/useQueryParams.ts b/packages/use-query-params/src/useQueryParams.ts index 00d2b21..f954e2c 100644 --- a/packages/use-query-params/src/useQueryParams.ts +++ b/packages/use-query-params/src/useQueryParams.ts @@ -1,5 +1,6 @@ import { useEffect, useMemo, useRef, useState } from 'react'; import { + ToBeEncodedValueMap, DecodedValueMap, QueryParamConfig, QueryParamConfigMap, @@ -23,9 +24,9 @@ import { enqueueUpdate } from './updateSearchString'; import { serializeUrlNameMap } from './urlName'; // for multiple param config -type ChangesType = - | Partial - | ((latestValues: DecodedValueMapType) => Partial); +type ChangesType = + | Partial> + | ((latestValues: DecodedValueMap) => Partial>); type UseQueryParamsResult = [ DecodedValueMap,