diff --git a/packages/nuqs/src/parsers.ts b/packages/nuqs/src/parsers.ts index 82973a601..9a94681b2 100644 --- a/packages/nuqs/src/parsers.ts +++ b/packages/nuqs/src/parsers.ts @@ -421,13 +421,13 @@ export function parseAsArrayOf( } type inferSingleParserType = Parser extends ParserBuilder< - infer Type + infer Value > & { - defaultValue: infer Type + defaultValue: infer Value } - ? Type - : Parser extends ParserBuilder - ? Type | null + ? Value + : Parser extends ParserBuilder + ? Value | null : never type inferParserRecordType>> = { diff --git a/packages/nuqs/src/serializer.test.ts b/packages/nuqs/src/serializer.test.ts index e924cc660..5ef06ae53 100644 --- a/packages/nuqs/src/serializer.test.ts +++ b/packages/nuqs/src/serializer.test.ts @@ -86,6 +86,20 @@ describe('serializer', () => { const result = serialize('?str=foo&external=kept', null) expect(result).toBe('?external=kept') }) + test('clears value when setting null for search param that has a default value', () => { + const serialize = createSerializer({ + int: parseAsInteger.withDefault(0) + }) + const result = serialize('?int=1&str=foo', { int: null }) + expect(result).toBe('?str=foo') + }) + test('clears value when setting null for search param that is set to its default value', () => { + const serialize = createSerializer({ + int: parseAsInteger.withDefault(0) + }) + const result = serialize('?int=0&str=foo', { int: null }) + expect(result).toBe('?str=foo') + }) test('clears value when setting the default value (`clearOnDefault: true` is the default)', () => { const serialize = createSerializer({ int: parseAsInteger.withDefault(0), diff --git a/packages/nuqs/src/serializer.ts b/packages/nuqs/src/serializer.ts index 6b9b2a540..272c05b18 100644 --- a/packages/nuqs/src/serializer.ts +++ b/packages/nuqs/src/serializer.ts @@ -1,4 +1,4 @@ -import type { Options } from './defs' +import type { Nullable, Options } from './defs' import type { inferParserType, ParserBuilder } from './parsers' import { renderQueryString } from './url-encoding' @@ -16,7 +16,7 @@ export function createSerializer< urlKeys?: Partial> } = {} ) { - type Values = Partial> + type Values = Partial>> /** * Generate a query string for the given values. diff --git a/packages/nuqs/src/tests/serializer.test-d.ts b/packages/nuqs/src/tests/serializer.test-d.ts index 55a5eaf73..f07eb5215 100644 --- a/packages/nuqs/src/tests/serializer.test-d.ts +++ b/packages/nuqs/src/tests/serializer.test-d.ts @@ -48,3 +48,16 @@ import { createSerializer, parseAsInteger, parseAsString } from '../../dist' serialize({ nope: null }) }) } + +// It accepts null for values +{ + const serialize = createSerializer({ + foo: parseAsInteger, + bar: parseAsInteger.withDefault(0) + }) + // Should accept number | null | undefined + expectType(serialize({ foo: null })) + expectType(serialize({ foo: undefined })) + expectType(serialize({ bar: null })) + expectType(serialize({ bar: undefined })) +}