Search code examples
node.jstypescriptaxiosjson-deserializationtsc

How can I cast a string to number in an response using axios?


I am using Axios to execute a GET request to a public API. This API return a numeric value as string. I need to cast this value a numeric value. My application runs using tsc, so I expect the result of my object to be a numeric value, but it's not.

Axios Response

[
  {
    "name": "foo1",
    "value": "8123.3000"
  },
  {
    "name": "foo2",
    "value": "5132.2003"
  },
  {
    "name": "foo3",
    "value": "622.0000"
  }
]

Expected Output

[
  {
    "name": "foo1",
    "value": 8123.3
  },
  {
    "name": "foo2",
    "value": 5132.2003
  },
  {
    "name": "foo3",
    "value": 622
  }
]

My code is very simple,

interface MyObj {
  myString: string;
  myNumber: number;
}

(async () => {
  let { data }: AxiosResponse<MyObj> = await axios.get<MyObj>("/public/data");
  console.log(data);
})();

I try to use interface, class, the interface Number. Nothing worked.

I leave an example of code to try it.

How can I get the expected output without manually converting each value one by one?


Solution

  • Axios does not change the type of properties in the response. Please verify that the server does not send you the wrong types.


    Edit

    From your comment, it seems that the server sends you the vslue as string instead of as number. In this case I would suggest working with Ajv (https://github.com/ajv-validator/ajv) so you can create a schema that describes how the response looks like. Ajv cn also transform the value from string to number for you:

    const Ajv = require('ajv')
    
    const ajv = new Ajv({
      // allow chaning the type of some values from type X to type Y. depends on the source and target type:
      // https://ajv.js.org/guide/modifying-data.html#coercing-data-types
      // X => Y rules: https://ajv.js.org/coercion.html
      coerceTypes: true,
    })
    
    const schema = {
      type: 'array',
      items: {
        type: 'object',
        properties: {
          name: { type: 'string' },
          value: { type: 'number' },
        },
        required: ['name', 'value'],
        additionalProperties: false,
      },
    }
    
    const data = { name: 1, value: '1.1' }
    
    console.log(typeof data.value === 'number') // false!
    
    const valid = ajv.validate(schema, data)
    if (!valid) {
      console.log(ajv.errors)
      process.exit(1)
    }
    
    console.log(typeof data.value === 'number') // true!