0

I've got a problem for some time

let's have this:

export abstract class abstractClass {
    abstract thing(): string
}

export class c1 extends abstractClass {
    thing(): string {
        return "hello"
    }
}

export class c2 extends abstractClass {
    thing(): string {
        return "world"
    }
}

export interface simpleInter {
    el: typeof abstractClass
}

const cls: simpleInter[] = [];
cls.push({
    el: c1
},{
    el: c2
})

for (const classObj of cls) {
    const c = new (classObj.el)() // error: Cannot create an instance of an abstract class. ts(2511)
    console.log(c.thing())
}

What I can't seems to answer is how can I make understand the compiler understand that I want as a type classes that extends my abstractClass

Avior
  • 481
  • 6
  • 18

2 Answers2

1

Define a constructor function interface CConstructor, use it as base type for your concrete classes instead of typeof abstractClass and you should be good to go.

export interface CConstructor {
    new(): abstractClass
}

export abstract class abstractClass {
    abstract thing(): string
}

export class c1 extends abstractClass {
    thing(): string {
        return "hello"
    }
}

export class c2 extends abstractClass {
    thing(): string {
        return "world"
    }
}

const cls: CConstructor[] = [c1, c2];

for (const classObj of cls) {
    const c = new (classObj)()
    console.log(c.thing())
}

Update:

new(): abstractClass in CConstructor is called a "Construct Signature", which can be created by adding the new keyword in front of a call signature. For more infos, have a look at the new TS handbook page.

ford04
  • 66,267
  • 20
  • 199
  • 171
0

So far i can unserstand you want to instanciate your clases dynmically. So here i can referr to: Dynamic instantiation in JavaScript

For Autocompletion you can cast later to the desired object.

Iam not shure if this finally helps you but maybe this bings you a little bit closer to the solution:

interface simpleInter {
  el: string;
}

const cls: simpleInter[] = [];
cls.push({
  el: 'c1'
},{
  el: 'c2'
});

function instantiate(className: string, args: any) {
  var o, f, c;
  c = window[className]; // get reference to class constructor function
  f = function(){}; // dummy function
  f.prototype = c.prototype; // reference same prototype
  o = new f(); // instantiate dummy function to copy prototype properties
  c.apply(o, args); // call class constructor, supplying new object as context
  o.constructor = c; // assign correct constructor (not f)
  return o;
}

for (const classObj of cls) {
  const c = instantiate(classObj.el, []); // error: Cannot create an instance of an abstract class. ts(2511)
  console.log(c.thing());
}