Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Invalid paramsSerializer TS type #5058

Closed
pegiadise opened this issue Oct 7, 2022 · 18 comments
Closed

Invalid paramsSerializer TS type #5058

pegiadise opened this issue Oct 7, 2022 · 18 comments

Comments

@pegiadise
Copy link

Describe the bug

The TS interface for paramsSerializer key in the AxiosRequestConfig is wrong / incomplete.

To Reproduce

Try to add a custom paramsSerializer function

  config.paramsSerializer = (params) => qs.stringify(params, { arrayFormat: 'repeat' })

Expected behavior

I can add a custom paramsSerializer function without getting type errors

Environment

  • Axios Version: 1.1.0
  • TypeScript Version: 4.7.4

Additional context/Screenshots

Screenshot 2022-10-07 at 11 51 19

@R3VoLuT1OneR
Copy link

@pegiadise Just had same issue now, I found the encode option in paramsSerializer.

To fix the error you need to do next:

config.paramsSerializer = {
  encode: (params) => qs.stringify(params, { arrayFormat: 'repeat' })
}

@pegiadise
Copy link
Author

pegiadise commented Oct 7, 2022

@pegiadise Just had same issue now, I found the encode option in paramsSerializer.

To fix the error you need to do next:

config.paramsSerializer = {
  encode: (params) => qs.stringify(params, { arrayFormat: 'repeat' })
}

@R3VoLuT1OneR First of all thanks for checking the issue. There is either a bug with this or some breaking changes that are not documented. Explaining by example:

  config.paramsSerializer = {
    encode: (params) => {
      console.log('params =>', params)

      return qs.stringify(params, { arrayFormat: 'repeat' })
    },
  }

Screenshot 2022-10-07 at 15 59 08

As you can see, the encode function is getting invoked for every param key and value of the params separately. I guess this was intentional, since the type is now called ParamEncoder and it kinda points towards a functionality change there. Leaving this open for reference until we can replicate previous behavior.

@DigitalBrainJS
Copy link
Collaborator

DigitalBrainJS commented Oct 7, 2022

Yes, the paramsSerializer option now has a totally different interface/implementation.
The encode option is primarily for custom data escaping. The custom key/value pair encoder is not currently supported for query params (only supported for FormData pairs), although it is defined as a visitor method in the TS interface, it is currently ignored. Its support will be added soon.
Basically, Axios has its own encoder that handles common cases of encoding nested data structures, so most users won't encounter the need for custom parameter conversions.

@yudielcurbelo
Copy link

This is also affecting me.

@RNR1
Copy link

RNR1 commented Oct 7, 2022

Affecting me as well, if it's possible to add native support for the same "array format: repeat" behavior it will be amazing!

@DigitalBrainJS
Copy link
Collaborator

DigitalBrainJS commented Oct 7, 2022

@RNR1 Axios already supports this out of the box. By default, Axios encodes arrays in "bracket" format but supports 3 qs formats except "comma".

qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'indices' }) ==> config.paramsSerializer.indexes = true // 'a[0]=b&a[1]=c'
qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'brackets' }) ==> config.paramsSerializer.indexes = false// 'a[]=b&a[]=c' // **Default**
qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'repeat' }) ==> config.paramsSerializer.indexes = null// 'a=b&a=c'
qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'comma' }) ==> **not supported** // 'a=b,c'

So to encode in arrayFormat: 'repeat' you need to do the following:

  const {data} = await axios.get('https://postman-echo.com/get', {
    params: {
      a: ['b', 'c', 'd']
    },
    paramsSerializer: {
      indexes: null // by default: false
    }
  });

Echo response:

{
  args: { a: [ 'b', 'c', 'd' ] },
  headers: {
    'x-forwarded-proto': 'https',
    'x-forwarded-port': '443',
    host: 'postman-echo.com',
    'x-amzn-trace-id': 'Root=1-63409c06-5d9fc0344ceaf9715466e0e3',
    accept: 'application/json, text/plain, */*',
    'user-agent': 'axios/1.1.0',
    'accept-encoding': 'gzip, deflate, br'
  },
  url: 'https://postman-echo.com/get?a=b&a=c&a=d' 
}

@GuichiZhao
Copy link

@DigitalBrainJS

qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'indices' }) ==> config.paramsSerializer.indexes = true // 'a[0]=b&a[1]=c'
qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'brackets' }) ==> config.paramsSerializer.indexes = false// 'a[]=b&a[]=c' // **Default**
qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'repeat' }) ==> config.paramsSerializer.indexes = null// 'a=b&a=c'
qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'comma' }) ==> **not supported** // 'a=b,c'

is really helpful, it should be added to the official documentation

@pegiadise
Copy link
Author

To summarize, at time of writing (axios@1.1.2):

  1. to alter array param notation in the query string use @DigitalBrainJS's answer
  2. more fine-grained altering on the params object will be provided via the visitor method in future versions.

@doits
Copy link

doits commented Oct 10, 2022

Is there probably a difference with nested objects like { a: [{ name: 'abc' }] }?

qs gives:

qs.stringify({ a: [{ name: 'abc' }], b: ['x', 'y'] }, { arrayFormat: 'brackets' })
=> 'a[][name]=abc&b[]=x&b[]=y'

Looks like axios adds an index even with config.paramsSerializer.indexes = false:

a[0][name]=abc&b[]=x&b[]=y

Or is there an error on my side?

Edit: Just confirmed it, Axios adds an index in this case which I think it should't

@doits
Copy link

doits commented Oct 11, 2022

Created #5094 to track it.

@pegiadise
Copy link
Author

Relevant PR: #5113

@codeyourwayup
Copy link

@pegiadise Just had same issue now, I found the encode option in paramsSerializer.

To fix the error you need to do next:

config.paramsSerializer = {
  encode: (params) => qs.stringify(params, { arrayFormat: 'repeat' })
}

worked. maybe because of outdated version

@rhues
Copy link

rhues commented Jan 6, 2023

Undocumented API change. Not cool.

@dduft
Copy link

dduft commented Jan 12, 2023

Shouldn't it be:

  paramsSerializer: {
      serialize: (params) => {
          return qs.stringify(params, { arrayFormat: 'repeat' })
      }
  }

?

@alete89
Copy link

alete89 commented Jan 17, 2023

Shouldn't it be:

  paramsSerializer: {
      serialize: (params) => {
          return qs.stringify(params, { arrayFormat: 'repeat' })
      }
  }

?

This makes total sense for me and worked in my case.

@babazookz
Copy link

Shouldn't it be:

  paramsSerializer: {
      serialize: (params) => {
          return qs.stringify(params, { arrayFormat: 'repeat' })
      }
  }

?

Helped in my case.

@MahendraBishnoi29
Copy link

how do i fix this in my case? @babazookz @alete89 @dduft

const axiosClient = axios.create({
  baseURL: baseUrl,
  paramsSerializer: (params) => queryString.stringify({ params }),  // Error is coming from this line
});

error message: Type '(params: any) => string' has no properties in common with type 'ParamsSerializerOptions'

@ivan-palatov
Copy link

how do i fix this in my case? @babazookz @alete89 @dduft

const axiosClient = axios.create({
  baseURL: baseUrl,
  paramsSerializer: (params) => queryString.stringify({ params }),  // Error is coming from this line
});

error message: Type '(params: any) => string' has no properties in common with type 'ParamsSerializerOptions'

 paramsSerializer: {
      serialize: (params) => {
          return queryString.stringify({ params })
      }
  }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests