Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.5k views
in Technique[技术] by (71.8m points)

angularjs - 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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

57.0k users

...