question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

URLSearchParams API should accept numbers for values

See original GitHub issue

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: https://github.com/microsoft/TypeScript/issues/15338

Issue Analytics

  • State:open
  • Created 4 years ago
  • Reactions:54
  • Comments:12 (1 by maintainers)

github_iconTop GitHub Comments

31reactions
nmaincommented, Aug 20, 2019

I personally would prefer not to see this change. The automatic coercion of non-strings to strings that exists in many DOM apis is very implicit and I like that typescript is more strict about it, instead forcing me to explicitly Number() or .toString() a numeric that is going to be used as a string.

28reactions
segevofercommented, Sep 3, 2019

I actually agree with @artyil This example also demonstrate the issue:

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

The spec of URLSearchParams doesn’t specify the value type of that object,

Forcing code like this, is too strict, and weird:

const url1 = new URLSearchParams({ foo: false.toString() })

So it should support string|number|boolean

Read more comments on GitHub >

github_iconTop Results From Across the Web

Typescript doesn't allow to use number/array ... - Stack Overflow
A URL is per default a single string, therefore the method only needs to accept a string. Using typescript, you can just do...
Read more >
URLSearchParams.values() - Web APIs - MDN Web Docs
The values() method of the URLsearchParams interface returns an iterator allowing iteration through all values contained in this object.
Read more >
Easy URL manipulation with URLSearchParams
The URLSearchParams API provides a consistent interface to the bits and ... Given a URL string, you can easily extract parameter values:
Read more >
How to easily manipulate URL search parameters in JavaScript
When making API requests, we'll typically need to append query parameters to the URL. With the URLSearchParams API, we can simply pass an ......
Read more >
Query string | Node.js v19.3.0 Documentation
Use <URLSearchParams> when performance is not critical or when compatibility ... <number[]> | <bigint[]> | <boolean[]> The numeric values must be finite.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found