3

Having a class (e.g. WikipediaSearchResult) with a few properties in TypeScript, is it possible to access them? Maybe this question is a bit naive, but I'm wondering if I could write following code without duplicated property names:

function mergeTo(from:any, to:any={}, properties:Array<string>=[]) {
  if (!!from) {
    for (var property of properties) {
      // no deep copy here ;-)
      to[property] = from[property];
    }
  }
}

class WikipediaSearchResult /* implements IWikipediaSearchResult */ {

  lang:string;
  summary:string;
  title:string;
  wikipediaUrl:string;

  constructor(obj?:any) {

    mergeTo(obj, this, [
      // --> How to avoid this list? <--
      'lang', 'summary', 'title', 'wikipediaUrl'
    ]);

  }

}

var result = new WikipediaSearchResult({
  title: 'Zürich', 
  wikipediaUrl: 'https://en.wikipedia.org/wiki/Z%C3%BCrich'
});

console.log(result);

Of course there are some 3rd party libraries such as Underscore.js, but it differs from e.g. _.clone(...) since I do only want to clone specific properties and ignoring all other properties which may be provided by obj respectively from.

Another way might be using e.g. _.create(WikipediaSearchResult.prototype, { title: 'Zürich' }), haven't tried it yet but it will use the JavaScript prototype property. It would be great to use TypeScript internal mechanism.

An idea which I came up with is to create a "dummy" instance and reading its key. I'm wondering if someone comes up with better variant?

2
  • why don't you iterate over from? for (var property in from) { to[property] = from[property]; } Commented Jan 27, 2016 at 13:52
  • from (any) might have more properties which should not be set in to Commented Jan 27, 2016 at 13:53

2 Answers 2

1

Initializing the properties of class WikipediaSearchResult allows using this as a "template":

function mergeTo(from:any, to:any={}, properties:Array<string>=[]) {
  // same as in question
}

function mergeTo2(from:Object, to:Object):Object {
  // _.keys from underscore
  return mergeTo(from, to, _.keys(to));
}

class WikipediaSearchResult {

  lang:string = undefined;
  summary:string = undefined;
  title:string = undefined;
  wikipediaUrl:string = undefined;

  constructor(obj?:any) {
     util.mergeTo2(obj, this);
  }

}

var result = new WikipediaSearchResult({
  title: 'Zürich', 
  wikipediaUrl: 'https://en.wikipedia.org/wiki/Z%C3%BCrich'
});

console.log(result);

Still looking for other variants...

Sign up to request clarification or add additional context in comments.

Comments

1

You can apply to each of the copiable properties a custom decorator:

  @Copiable
  lang:string;

Then inside @copiable decorator function you will store target property name in some static collection.

function Copiable(target: any, key: string) 
{
    CopiableProperties.push(key); 
}

Then later in mergeTo method you will be able to iterate over all copiable property names stored in CopiableProperties.

It might be a bit overkill but it will allow you to avoid duplicates. Hope this helps.

3 Comments

Interesting approach but as you stated it's a bit overkill. And another question might arise: Where to store this collection?
For my purposes I have a special public helper static class dedicated to contain such 'meta' information.
I'll like the idea of using decorators(!) but it does not help to make the code more readable or maintanable. I rather go with my answer because of these reasons. Bring me an argument why your solution is better than mine and I am going to change the accepted answer to yours. ;)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.