StuperUser
StuperUser

Reputation: 10850

How to use TypeScript to map a large object to a smaller interface?

I have an object returned from a server that contains e.g.

{
    lorem: 1,
    ipsa: [2,3],
    dolor: { sit: 'amet', consectetur: 'adipiscing'},
    elit: [{you: 'get'}, {the: 'picture'}]
}

and a TypeScript interface of

export interface smallerInterface {
    ipsa: number[];
    elit: any[];
}

I'm saving the returned object into IndexedDb, and don't want to save any fields that are not present on the interface.

I have tried casting fullObject as smallerInterface and <smallerInterface>fullObject, but when saving this object into the IndexedDb, it is still including the fields lorem and dolor.

How can I map the full object to this smaller interface (hopefully without writing an explicit map function) or otherwise force TypeScript to ignore these fields?

Upvotes: 8

Views: 5504

Answers (2)

20B2
20B2

Reputation: 2141

I have to break down a bigger object from API to Smaller classes. First of all I created smaller class using the same property name as the object from API.

export class SmallerClass {
    prop1: type,
    prop2: type,
    ...
   constructor(){
       // set default values to the props
   }
}

I use constructor to have an object with default values on creating an instance of the object.

let myObj = new SmallerClass();

let apiObj = `API Call`;

Then after receiving object from API, the instance of the SmallerClass can be instantiated using either of following methoods:
1. Using key in Object syntax

Object.keys(this.myObj).map((key) => {
   if (key in this.apiObj) {
      this.myObj [key] = this.apiObj[key];
   }
});

2. Using hasOwnProperty

Object.keys(this.myObj).map((key) => {
   if (this.apiObj.hasOwnProperty(key)) {
      this.myObj[key] = this.apiObj[key];
   }
});

Upvotes: -1

casieber
casieber

Reputation: 7542

Typescript types do not have a runtime impact and so casting an object to different types will have no tangible effect on that object at runtime.

One of the goals of TypesScript:

  1. Use a consistent, fully erasable, structural type system.

emphasis added by me

If you want to modify an object you need code beyond types to perform the modification. Given the inability to convert between values and types like you are looking for (see this issue for further discussion), you will need to do something like:

export interface SmallerInterface {
    ipsa: number[];
    elit: any[];
}

export const smallerKeys = ['ipsa', 'elit'];

// Later once you have a result
const result = await makeRequest();
const reducedResult = smallerKeys.reduce((obj, key) =>
    ({ 
        ...obj, 
        [key]: result[key],
    }),
    {}
) as SmallerInterface;

Upvotes: 5

Related Questions