How to reduce javascript object to contain only interface properties

When using typescript, the declared interface might look like this:

interface MyInterface { test: string; } 

And an implementation with an additional property might be something like this:

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

Example (here the "reduced" variable still contains the "newTest" property):

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

Question

In general, how can you make the "reduced" variable contain only properties declared in the "MyInterface" interface.

Why

The problem arises when trying to use a "reduced" variable with angular.toJson before sending it to the recreation service - the toJson method converts the new variable newTest, even if it is not available in the instance at compile time, and this forces the service to not accept json because he possesses properties that should not be.

+20
javascript angularjs typescript
source share
7 answers

Are you trying to set or assign only the properties listed on the interface? This type of functionality is not available in TypeScript, but it is very simple to write a function to execute the behavior you are looking for.

 interface IPerson { name: string; } class Person implements IPerson { name: string = ''; } class Staff implements IPerson { name: string = ''; position: string = ''; } var jimStaff: Staff = { name: 'Jim', position: 'Programmer' }; var jim: Person = new Person(); limitedAssign(jimStaff, jim); console.log(jim); function limitedAssign<T,S>(source: T, destination: S): void { for (var prop in destination) { if (source[prop] && destination.hasOwnProperty(prop)) { destination[prop] = source[prop]; } } } 
+2
source share

This is impossible to do. The reason is that the interface is a Typescript construct and the portable JS code is empty.

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

Thus, at run time there is nothing to work with - there are no properties for polling.

@ Jamesmoey's answer explains a workaround to achieve the desired result. A similar solution that I use is to simply define the "interface" as a class -

 class MyInterface { test: string = undefined; } 

Then you can use lodash to select properties from the "interface" to embed in your 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 helped me well without getting stuck in the semantics about whether it is actually an interface and / or naming conventions (e.g. IMyInterface or MyInterface ), and allows you to prototype and test modules.

+2
source share

In your example, the newTest property is not available through the reduced variable, so the goal is to use types. typescript does type checking, but does not manipulate object properties.

+1
source share

TS 2.1 has Object Spread and Rest, so now you can:

 var my: MyTest = {test: "hello", newTest: "world"} var { test, ...reduced } = my; 

After that, the abbreviation will contain all properties except the "test".

+1
source share

In general, how can you make the "reduced" variable contain only properties declared in the "MyInterface" interface.

Since TypeScript is structural, this means that everything that contains the relevant information is Type Compatible and therefore assigned.

However, TypeScript 1.6 will get the concept of freshness . This will simplify typo recognition (note that freshness only applies to object literals):

 // ERROR : `newText` does not exist on `MyInterface` var reduced: MyInterface = {test: "hello", newTest: "world"}; 
0
source share

A simple example:

 let all_animals = { cat: 'bob', dog: 'puka', fish: 'blup' }; const { cat, ...another_animals } = all_animals; console.log(cat); // bob 
0
source share

Duplicate is possible:

TypeScript or JavaScript casts

You must "distinguish" your meaning from another type.

some good examples are also here: http://blogs.microsoft.co.il/gilf/2013/01/18/using-casting-in-typescript/

 this.span = <HTMLSpanElement>document.createElement('span'); 

hope this helps?

-4
source share

All Articles