redOctober13
redOctober13

Reputation: 3974

Possible to have a Typescript interface that differs from what the API returns?

I guess this is kind of a general programming question, but I'm still basically a beginner when it comes to AJAX-type stuff.

So let's say I'm consuming an API where the creators didn't care about naming stuff nicely (or at least, not the way I would do it), such that the response looks like this:

{
  data: [{
    sdt: '2018-10-12',
    firstnm: 'Stevo',
    pos: 'Assistant to the Manager'
  }]
}

but I want my interface to have clearer names using a camelCase convention like so:

export interface IHiringData {
  startDate: string,
  firstName: string,
  position: string
}

Is this possible? Or am I stuck defining an interface that mimics whatever the API returns? If I can use the interface I want, what's a good way to map the returned data to the Typescript interface?

Upvotes: 0

Views: 184

Answers (2)

Aaron Beall
Aaron Beall

Reputation: 52133

Another solution is to use the JSON reviver function to remap certain keys to better names:

interface Employees {
  data: Employee[];
}

interface Employee {
  startDate: string;
  firstName: string;
  position: string;
}

const json = `{
  "data": [{
    "sdt": "2018-10-12",
    "firstnm": "Stevo",
    "pos": "Assistant to the Manager"
  }]
}`

const remapKeys = {
  "sdt": "startDate",
  "firstnm": "firstName",
  "pos": "position"
}

function reviver(this: any, key: string, val: any) {
  if (key in remapKeys)
    this[remapKeys[key as keyof typeof remapKeys]] = val;
  else
    return val;
}

const obj: Employees  = JSON.parse(json, reviver);

Result:

{
  data: [
    {
      startDate: "2018-10-12",
      firstName: "Stevo",
      position: "Assistant to the Manager"
    }
  ]
}

Example: Playground link

One possible advantage to this approach is that you could parse a large tree of JSON data and keys will be remapped no matter where they are found.

With any solution note that JSON.parse() returns any and does not guarantee your mapping actually matches your interface. You'd need to write a full deserializer that throws errors on unexpected or missing data for that level of safety.

Upvotes: 1

Numé
Numé

Reputation: 329

One solution is to simply map the JSON-data to a new object which matches your interface.

export interface IHiringData {
  startDate: string
  firstName: string
  position: string
}

const json = {
  data: [{
    sdt: '2018-10-12',
    firstnm: 'Stevo',
    pos: 'Assistant to the Manager'
  }]
}

const hiringData: IHiringData[] = json.data.map(x => ({
  startDate: x.sdt,
  firstName: x.firstnm,
  position: x.pos
}))

Upvotes: 3

Related Questions