Lexi
Lexi

Reputation: 1730

What type is a constructor?

I have something along these lines in a typescript application I'm building

class Thing {
    static ReleventInfo: string
}
class Foo extends Thing { }
class Bar extends Thing { }
class Baz extends Thing { }

var things = {
    foo: Foo,
    bar: Bar,
    baz: Baz,
}


function FooPlease(): Foo {
    return new things.foo;
}

function ThingPlease(thing: string): Thing {
    if (!things[thing])
        return null;
    var ctor = things[thing];
    // ctor now has type of 'any', can't access 'ReventInfo' nicely.
    var newThing = new ctor();
    // newThing now has type of 'any'
    return newThing;
}

Which works, but typescript (and Intellisense) lose track of what type ctor and therefore newthing are, which is a problem because I wish to access static properties and object methods on them. What type should I say the var is? Intellisense unhelpfully provides this information: (var) things = { foo: typeof(Foo) }(class) Foo

Upvotes: 0

Views: 101

Answers (2)

Lexi
Lexi

Reputation: 1730

Based on Steve's answer, I realised that I could define the map with the map type { [thingType: string]: typeof Thing } rather than leaving it implicit - this results in all accesses returning a typeof Thing without a cast!

class Thing {
    static ReleventInfo: string
}
class Foo extends Thing { }
class Bar extends Thing { }
class Baz extends Thing { }

var things: { [thingType: string]: typeof Thing } = {
    foo: Foo,
    bar: Bar,
    baz: Baz,
}


function FooPlease(): Foo {
    return new things.foo;
}

function ThingPlease(thing: string): Thing {
    if (!things[thing])
        return null;
    var ctor = things[thing];
    var newThing = new ctor();
    return newThing;
}

Upvotes: 1

Fenton
Fenton

Reputation: 250812

Because TypeScript can't know what possible string may be passed to ThingPlease it can't determine the type.

You need to give it a hint using a type assertion:

var ctor = <typeof Thing>things[thing];

Full example below:

class Thing {
    static ReleventInfo: string
}

class Foo extends Thing { }
class Bar extends Thing { }
class Baz extends Thing { }

var things = {
    foo: Foo,
    bar: Bar,
    baz: Baz,
}


function FooPlease(): Foo {
    return new things.foo;
}

function ThingPlease(thing: string): Thing {
    if (!things[thing]) {
        return null;
    }

    // ctor is `typeof Thing`
    var ctor = <typeof Thing>things[thing];

    // newThing is `Thing`
    var newThing = new ctor();

    return newThing;
}

Upvotes: 1

Related Questions