Home > Mobile >  Handle typescript error when db is sending snakecase attributes and front accepts only pascalcase
Handle typescript error when db is sending snakecase attributes and front accepts only pascalcase

Time:06-09

I'm looking for the best practice to do a conversion when my api is sending me a snake case value and my front only accepts pascal case attributes.

Here is my problem :

Front Request

I have an axios request that gets multiple users. Let's say axios.get('/users')

Api answer

My api gives me a list of users :

[{
  id: 10
  last_name: 'Foo'
  first_name: 'Bar'
},{
  id: 11
  last_name: 'Baz'
  first_name: 'Bob'
}]

Typescript User type

Now I have a User type and my typescript only accepts pascal case attributes :

type User = {
    id: number,
    lastName: string,
    firstName: string
}

Typing my axios response

And now I'm passing the received users to an array users but the error occurs when I want to associate lastName with last_name and firstName with first_name.

let users: User[] = []

const res = await axios.get('/users')
res.data.forEach((user: User) => {
  users.push({
    id: user.id,
    lastName: user.last_name, // Typescript Error
    firstName: user.first_name // Typescript Error
  })
}

return users

Do anyone have a solution to this problème ? Do I need to tell my array that the user received by the api is of any type ? What is the best practice ?

CodePudding user response:

You have two approaches:

Approach 1: Type the response from API differently

Because your response data has different keys, you can't really type it as User. You should have a separate type for it.

type UserData = {
    id: number,
    last_name: string,
    first_name: string
}

This would, of course, double the maintenance effort whenever you need to change some field's name and is more error-prone. However it is also more flexible.

Approach 2: Convert response's field names before using it.

You can write a small utility that recursively converts field names from snake_case to camelCase. After that, you can type the response correctly as User. I use this approach personally and it works well, but typing the code is a little tricky. Below is the code I usually use, it might not be perfect and everyone is welcome to give feedback.

import { camelCase } from 'lodash-es';

export type JSONValue =
  | string
  | number
  | boolean
  | JSONValue[]
  | { [key: string]: JSONValue };

const recursivelyTransformKeys = (obj: JSONValue): JSONValue => {
  if (typeof obj !== 'object' || obj === null) {
    return obj;
  }

  if (Array.isArray(obj)) {
    return obj.map(recursivelyTransformKeys);
  }

  const result: JSONValue = {};
  Object.entries(obj).forEach(([k, v]) => {
    result[camelCase(k)] = recursivelyTransformKeys(v);
  });
  return result;
};

Then use it in your code like so:

const res = await axios.get('/users')
recursivelyTransformKeys(res.data).forEach((user: User) => {
  users.push(user);
}

CodePudding user response:

If you want to use Typescript to resolve above scenario then following way you can achieve it

interface user{
    id: number,
    lastName: string,
    firstName: string
}
interface userResponse{
    last_name: string,
    first_name: string
}
type User = userResponse | user;

const anExampleVariable: user = {
    id: 123,
    lastName: "123",
    firstName: "12"
}

Another way is to create helper function, then loop through response key and user helper function to transform keys from snack_case to pascalCase

Here is the Helper function

function pascalCase(val){
  const ary = val.split("_");
  return ary[0] ary[1].charAt(0).toUpperCase() ary[1].slice(1)
}
  • Related