8

Before anyone marks this as duplicate please read below,

My scenario doesn't just involve TypeScript but also Angular2.

Objective

I need a method in app.component.ts which takes a string(Class Name) and creates a instance of that. The classes exist in other ts files.

Now to the use case: I have a method getWidgetObjectFromClassName(className : string) : Object{} which needs to return the instances of the class name which is in string format. Now the problem,

I tried using NameSpace and doing let instance = new SampleNS['OtherName'](); (SampleNS is a namespace), works perfectly fine in the case of single file.

But Now i have multiple ts files lets say interfaces.ts, classes.ts, otherclasses.ts. Im using export namespace SampleNS{} in interface.ts all works, next in classes.ts using the /// <reference path="interfaces.ts" /> and same namespace SampleNS.

Now my method getWidgetObjectFromClassName(className : string) : Object{} is in xyz.ts, and now which import should i give?, my point being if i say `import {SampleNS} from './interfaces'. The problem here is i can only import a single file's namespace(even though its the same) hence im creating instance is limited to the import of that specific file namespace.

Plunker Link https://plnkr.co/edit/pt90F34KPsGoHDpSUQFD?p=preview

6
  • What about creating a file that exports all your component, then you need to just import this file with a namespace and then you should be able to refer to all components the same way? Commented Jul 1, 2016 at 5:47
  • 3
    "Before anyone marks this as duplicate please read below," - No, I prefer to judge whether things are duplicates by flipping a coin. Commented Jul 1, 2016 at 5:48
  • ok gunter...trying out ur solution will get back... Commented Jul 1, 2016 at 5:48
  • @GünterZöchbauer its not able to locate the class even if i do so, should i post a plunker? Commented Jul 1, 2016 at 7:02
  • Plunker would be great. Commented Jul 1, 2016 at 7:11

2 Answers 2

13

Use as with imports like

import * as widgets from './lib';
...
this.widgetInstance = new widgets[className](); 

Plunker example

I remember this from another answer but I couldn't find it to give some credit :-/

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

1 Comment

As always u have been awesome!
4

You can use eval to create an object from the class name:

class SomeClass
{
    x: number;
    y: number;
    constructor() {
        this.x = this.y = 1;
    }

}



function getWidgetObjectFromClassName(className : string) : {}
{
    return eval("new " + className + "();");
}

console.log("%o", getWidgetObjectFromClassName("SomeClass"));

Playground here

6 Comments

This works perfectly fine, but now for my scenario, when i have my SomeClass on other ts files and even if i import it it cannot find it. Please Check
Probably you will need to include module or namespace: getWidgetObjectFromClassName("ModuleOrNamespace.SomeClass")
This is not a clean solution, but definitely works, Why downvote?
So far, the only solution I've found, thanks! Likely dangerous, though.
@Raffael could you explain why it is likely dangerous? Is it because ambiguity of the classname might cause the wrong class to be returned?
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.