Skip to content

URLSearchParams API should accept numbers for values #1568

Open
@artyil

Description

@artyil

Actual implementation of URLSearchParams.constructor and URLSearchParams.prototype.set methods in the browsers will accept any value as value, including number or Integer.

TLDR:
new URLSearchParams([['foo', 1]]) and new URLSearchParams().set('bar', 1) should compile without TS errors

It works in current implementation, because numeric value will be coerced to actual USVString value, which is a string.

Unfortunately, current TS definition of type URLSearchParams in lid.dom.d.ts will only allow strings for above mentioned setters. Below are the definitions.

I can understand that the definitions are mirroring the W3C specifications but I do believe it is not the expected experience for developers.

The actual definition enforces developers to make unnecessary operations (helpers / utils / map-reduces) to overcome TS errors 👋

Can we reconsider to allow values to be numeric to mentioned setters? This won't break any current bahavior or actual implementation.

Even as per MDN examples constructor and URLSearchParams.prototype.set it should work as expected:

// Pass in a sequence
var params3 = new URLSearchParams([["foo", 1],["bar", 2]]);

//Add a third parameter.
params.set('baz', 3);

Which works in browser but doesn't work in TS.

TypeScript Version: 3.4.3
output with tsc typescript@next

a.ts:3:34 - error TS2345: Argument of type '{ foo: number; bar: string; }' is not assignable to parameter of type 'string | Record<string, string> | URLSearchParams | string[][]'.
  Type '{ foo: number; bar: string; }' is not assignable to type 'string'.

3 const url2 = new URLSearchParams({ foo: 1, bar: '1' }) // <- FAILS
                                   ~~~~~~~~~~~~~~~~~~~~

a.ts:5:34 - error TS2345: Argument of type '(string | number)[][]' is not assignable to parameter of type 'string | Record<string, string> | URLSearchParams | string[][]'.
  Type '(string | number)[][]' is not assignable to type 'string[][]'.
    Type '(string | number)[]' is not assignable to type 'string[]'.
      Type 'string | number' is not assignable to type 'string'.
        Type 'number' is not assignable to type 'string'.

5 const url3 = new URLSearchParams([['foo', 1], ['bar', '1']]) // <- FAILS
                                   ~~~~~~~~~~~~~~~~~~~~~~~~~~

a.ts:8:17 - error TS2345: Argument of type '1' is not assignable to parameter of type 'string'.

8 url4.set('foo', 1); // <- FAILS
                  ~


Found 3 errors.

Search Terms:
Typescript URLSearchParams invalid constructor
Typescript URLSearchParams won't accept numbers as value
Typescript URLSearchParams won't accept numeric values
standard lib.dom.d.ts URLSearchParams allow numbers as values
Typescript URLSearchParams coercion number to string

Code

const url = new URLSearchParams({foo: 'bar'}) // <- OK 

const url2 = new URLSearchParams({ foo: 1, bar: '1' }) // <- FAILS

const url3 = new URLSearchParams([['foo', 1], ['bar', '1']]) // <- FAILS

const url4 = new URLSearchParams([['bar', '2']]) // <- OK
url4.set('foo', 1); // <- FAILS

Expected behavior:
All above cases should work, because numeric values are being coerced to strings

Actual behavior:
TS won't compile due to URLSearchParams definitions only accept string for value

interface URLSearchParams {
    /**
     * Appends a specified key/value pair as a new search parameter.
     */
    append(name: string, value: string): void;
    /**
     * Deletes the given search parameter, and its associated value, from the list of all search parameters.
     */
    delete(name: string): void;
    /**
     * Returns the first value associated to the given search parameter.
     */
    get(name: string): string | null;
    /**
     * Returns all the values association with a given search parameter.
     */
    getAll(name: string): string[];
    /**
     * Returns a Boolean indicating if such a search parameter exists.
     */
    has(name: string): boolean;
    /**
     * Sets the value associated to a given search parameter to the given value. If there were several values, delete the others.
     */
    set(name: string, value: string): void;
    sort(): void;
    forEach(callbackfn: (value: string, key: string, parent: URLSearchParams) => void, thisArg?: any): void;
}

declare var URLSearchParams: {
    prototype: URLSearchParams;
    new(init?: string[][] | Record<string, string> | string | URLSearchParams): URLSearchParams;
};

Playground Link:
link

Related Issues:
microsoft/TypeScript#15338

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions