0

Is it possible to convert the following piece of code to work with Typescript?

public shops: string[] = [
   "AShop",
   "BShop",
   "CShop",
];    

this.shops.forEach((shop, index) => {
    let instance = new window[shop](index);
    this.instances.push(instance);
});

The following approach doesn't work with Typescript because window is inexistent in the scope. I cannot compile it. (Although it would work with vanilla JS)

Is there a way to treat variable name shop in the loop as an expression and create a dynamic class based on it?

20
  • Where is defined purchasable? Commented Jan 11, 2017 at 20:46
  • @timocov Oops, fixed it. It was meant to be shop. Commented Jan 11, 2017 at 20:47
  • What exactly is the problem? Are you getting an error? Commented Jan 11, 2017 at 20:48
  • 1
    Do you have noImplicitAny compiler option enabled? Commented Jan 11, 2017 at 20:49
  • Try this: class BaseShop { } interface ShopContructor { new (index: number): BaseShop; } interface Window { [shop: string]: ShopContructor; } Commented Jan 11, 2017 at 20:57

2 Answers 2

1

Try this:

const shops: string[] = ["AShop", "BShop", "CShop"];

class BaseShop {
    public constructor(index: number) {
        console.log(index);
    }
 }

class AShop extends BaseShop { }
class BShop extends BaseShop { }
class CShop extends BaseShop { }

interface ShopContructor {
    new (index: number): BaseShop;
}

interface Window {
    AShop: ShopContructor;
    BShop: ShopContructor;
    CShop: ShopContructor;
    [shop: string]: ShopContructor;
}

window.AShop = AShop;
window.BShop = BShop;
window.CShop = CShop;

const instances: BaseShop[] = [];

shops.forEach((shop: string, index: number) => {
    let instance = new window[shop](index);
    instances.push(instance);
});

console.log(instances);
Sign up to request clarification or add additional context in comments.

2 Comments

Is there any way to get rid of window.AShop = AShop;? I would rather rely on a switch/case actually. Just wanted a magic trick to initialize all the array as a class.
You can add all classes to an array (instead of their names). const shops: ShopContructor[] = [AShop, BShop, CShop];
0

This is a weird structure, because if you have dynamic classes in the global scope you can't get good type checking for it at compile time. I'd suggest just using <any> here and getting it over with. If you expect certain type guarantees for the resulting instance, you should specify them explicitly using the variable type or casting:

this.shops.forEach((shop, index) => {
    let instance = new (<any>window)[shop](index);
    this.instances.push(instance);
});

4 Comments

Uncaught TypeError: window[shop] is not a function :(
@Aris But I don't have window[shop] in this code. I changed it to (<any>window)[shop].
@AsadSaeeduddin (<any>window)[shop] is compiled to window[shop]
@timocov Ah, I didn't realize this was a runtime error! So the OP doesn't even have the constructor functions in the global scope? Where are they?

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.