fromQueryParams
Parses a query string into an object. Supports repeated keys as arrays.
1/**
2 * Parses a query string into an object.
3 * Supports repeated keys as arrays.
4 *
5 * @param query - The query string (with or without leading '?').
6 * @returns An object with parsed query parameters.
7 */
8export function fromQueryParams(query: string): Record<string, string | string[]> {
9 const result: Record<string, string | string[]> = {};
10
11 query
12 .replace(/^\?/, '') // remove leading '?'
13 .split('&')
14 .filter(Boolean)
15 .forEach(part => {
16 const [rawKey, rawVal] = part.split('=');
17 const key = decodeURIComponent(rawKey);
18 const value = decodeURIComponent(rawVal || '');
19
20 if (result[key] === undefined) {
21 result[key] = value;
22 } else if (Array.isArray(result[key])) {
23 (result[key] as string[]).push(value);
24 } else {
25 result[key] = [result[key] as string, value];
26 }
27 });
28
29 return result;
30}
Handles Repeated Keys
Automatically groups repeated query parameters into arrays, preserving all values.
Robust Decoding
Uses
decodeURIComponent
for safe and accurate decoding of both keys and values.Flexible Input Format
Accepts query strings with or without a leading
?
, improving compatibility.No External Dependencies
Fully self-contained and avoids reliance on
URLSearchParams
or third-party libraries.
Tests | Examples
1test('fromQueryParams - single pair', () => {
2 expect(fromQueryParams('q=test')).toEqual({ q: 'test' });
3});
4
5test('fromQueryParams - multiple pairs', () => {
6 expect(fromQueryParams('q=js&sort=asc')).toEqual({ q: 'js', sort: 'asc' });
7});
8
9test('fromQueryParams - handles repeated keys as arrays', () => {
10 expect(fromQueryParams('tag=a&tag=b')).toEqual({ tag: ['a', 'b'] });
11});
12
13test('fromQueryParams - decodes values', () => {
14 expect(fromQueryParams('q=C%23%20%26%20Java')).toEqual({ q: 'C# & Java' });
15});
16
17test('fromQueryParams - handles empty value', () => {
18 expect(fromQueryParams('flag=')).toEqual({ flag: '' });
19});
20
21test('fromQueryParams - handles leading ?', () => {
22 expect(fromQueryParams('?a=1&b=2')).toEqual({ a: '1', b: '2' });
23});
24
25test('fromQueryParams - empty string returns empty object', () => {
26 expect(fromQueryParams('')).toEqual({});
27});
Common Use Cases
Reading Query Parameters on Page Load
Extract values from
location.search
for routing or conditional rendering.Restoring State from URL
Rehydrate filters, form values, or UI state encoded in the query string.
Processing Form Submissions
Parse query-encoded form submissions for validation or processing.
Analytics or Logging
Extract meaningful data from URLs for tracking or debugging purposes.