typescriptangulartypescript1.7

Reading property names from a class in TypeScript?


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?


Solution

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