Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to reduce javascript object to only contain properties from interface

When using typescript a declared interface could look like this:

interface MyInterface {   test: string; } 

And an implementation with extra property could be like this:

class MyTest implements MyInterface {   test: string;   newTest: string; } 

Example (here the variable 'reduced' still contain the property 'newTest'):

var test: MyTest = {test: "hello", newTest: "world"}  var reduced: MyInterface = test; // something clever is needed 

Question

In a general way, how can you make the 'reduced' variable to only contain the properties declared in the 'MyInterface' interface.

Why

The problem occur when trying to use the 'reduced' variable with angular.toJson before sending it to a rest service - the toJson method transforms the newTest variable, even if it's not accessible on the instance during compile, and this makes the rest service not accept the json since it has properties that shouldn't be there.

like image 913
Tomas F Avatar asked Aug 05 '15 10:08

Tomas F


People also ask

How do I remove all properties of an object?

Delete properties one-by-oneObject. keys(object). forEach(key => delete object[key]); This will clean the object by going through every non-prototype property and deleting it.

How many properties can a JavaScript object have?

JavaScript objects have two types of properties: data properties and accessor properties.


1 Answers

It is not possible to do this. The reason being interface is a Typescript construct and the transpiled JS code is empty

//this code transpiles to empty! interface MyInterface {   test: string; } 

Thus at runtime there is nothing to 'work with' - no properties exist to interrogate.

The answer by @jamesmoey explains a workaround to achieve the desired outcome. A similar solution I use is simply to define the 'interface' as a class -

class MyInterface {   test: string = undefined; } 

Then you can use lodash to pick the properties from the 'interface' to inject into you object:

import _ from 'lodash';  //npm i lodash  const before = { test: "hello", newTest: "world"}; let reduced = new MyInterface(); _.assign(reduced , _.pick(before, _.keys(reduced))); console.log('reduced', reduced)//contains only 'test' property 

see JSFiddle

This is a pragmatic solution that has served me well without getting bogged down on semantics about whether it actually is an interface and/or naming conventions (e.g. IMyInterface or MyInterface) and allows you to mock and unit test

like image 147
wal Avatar answered Sep 25 '22 06:09

wal