How to convert a "String" value to "Type" in Angular 2

16,013

Solution 1

I guess there is a way to get the type of a class by string but I don't know (I don't use TS). A simple workaround would be to

create a map from string to type

classes = {
  'MyClass1': MyClass1,
  'MyClass2': MyClass2,
  'Grid': Grid
}

and then just look the types up

class['Grid']

The disadvantage is that you need to know all supported classes in advance.

Solution 2

I don't know Angular 2 in depth, but in a well structured application it is straightforward and feasible to get a Type using a string, if you know the fully qualified name of the given Type:

let typeName = "GridPage";
let ComponentType = MyApp.Components[typeName];

If you are getting the following type error:

Index signature of object type implicitly has an 'any' type.

... then you will need to type cast the preceding namespace (object). I prefer asserting to any in this case, as it's shorter than defining an inline interface for a string-based index signature, and you effectively don't lose any type-safety:

let ComponentType = (MyApp.Components as any)[typeName];

Additionally, this approach also works perfectly with modules:

import * as Components from "./components";

let ComponentType = (Components as any)[typeName];
Share:
16,013
AishApp
Author by

AishApp

Hybrid Mobile Application Developer, Digitacode

Updated on June 18, 2022

Comments

  • AishApp
    AishApp almost 2 years

    I want to create a side menu in ionic 2 application where the page navigation component is placed in a external json file fetched with the help of menuService.getMenu function.

    MY JSON structure:

    "menu":[
            {
              "title":"Grid",
              "component":"GridPage"
            }
          ]
    

    My Ts:

        this.menuService.getMenu().then((menu) => {
        this.menu = menu;
        });
    
        openPage(menu) {
          console.log("menu", menu.component);
          nav.setRoot(menu.component);
        }
    

    Console log prints the string GridPage. I tried to convert using Type as Type(menu.component). But my result in console is a function with anonymous name. Someone please help me on getting the json string converted to component "Type" for navigation to work.

  • AishApp
    AishApp about 8 years
    Hi @John White. i am getting "cannot read property 'GridPage' of undefined error" on using var check = (<any>this.app.Components)[typevar]; Kindly help
  • John Weisz
    John Weisz about 8 years
    @Aish123 It means that this.app.Components is undefined. This is usually caused by file ordering issues if you compile into a single output file. If you are compiling into a single output file, try specifying reference paths for the compiler to know the correct file order. The error you are getting is not specific to getting types from strings.
  • AishApp
    AishApp about 8 years
    I am not sure whether the command in supported in angular2 typescript. i am getting syntax error in ts. File order does not matter in my case as i am importing all my files on initializing my app.
  • John Weisz
    John Weisz about 8 years
    @Aish123 What ts error do you mean? The "cannot read property ... of undefined" is not a Typescript compile error, it's a Javascript runtime error.
  • AishApp
    AishApp about 8 years
    typescript is not able to identify this.app.Components.
  • John Weisz
    John Weisz about 8 years
    @Aish123 What error message are you getting during compilation?
  • AishApp
    AishApp about 8 years
    i am getting "Unresolved javascript functions" on components. I guess Angular2 is not identifying the function components. Do i have to import any package for it.
  • John Weisz
    John Weisz about 8 years
    @Aish123 If you want to use a specific component type that was determined from a string, you will need to type cast. How else would the compiler know what type it is?
  • AishApp
    AishApp about 8 years
    Actually the question is to convert string to a "Type". I didnt mean some other datatype here. Kindly check the doc. I have imported this Type from angular2
  • esqew
    esqew almost 8 years
    Thank you! Got me out of a bind. This should probably be the accepted answer.
  • John Weisz
    John Weisz almost 7 years
    @JoseA This answer is more than a year old, nowadays it's preferred to use obj as Type instead (because <Type>obj is ambiguous in .tsx files). I've edited the answer accordingly.
  • Jose A
    Jose A almost 7 years
    @JohnWeisz: Thanks. What about in the following scenario?: <MyType>(<any>document.getElementById('my-id').getAttribute(‌​'custom-attribute'). This is not in respect of Angular, but Web Components.
  • John Weisz
    John Weisz almost 7 years
    @JoseA It would be simply (document.getElementById('my-id').getAttribute(‌​'custom-att‌​ribute') as any) as MyType, or document... as any as MyType.