user210757 user210757 - 9 days ago 5
TypeScript Question

Dynamic TypeScript Typing

Is there any way to have dynamic object properties in a TypeScript class, and add dynamic Typings in for TypeScript?

I have seen similar questions but none with a complete example like this -

interface IHasObjectName {
objectName: string;
}

class example<A extends IHasObjectName, B extends IHasObjectName> {

constructor(a: A, b: B) {
this[a.objectName] = function() { return a; };
this[b.objectName] = function() { return b; }
}
}

class Cat implements IHasObjectName {
objectName: string = "";
}

class Dog implements IHasObjectName {
objectName: string = "";
}

let cat = new Cat();
cat.objectName = "Cat";

let dog = new Dog();
dog.objectName = "Dog";

let test = new example<Cat,Dog>(cat, dog);

// ??? TYPESCRIPT DOESN'T KNOW ABOUT THESE DYNAMIC PROPERTIES
// HOW DO I MAKE THIS WORK?
let d = test.Dog();
let c = test.Cat();

// I know I could access like this
// let d = test["Dog"]();
// but I want to access like function and have it typed

Answer

You can use a factory function and intersection:

function factory<A extends IHasObjectName, B extends IHasObjectName, C>(a: A, b: B): example<A, B> & C {
    return new example<Cat, Dog>(a, b) as C;
}
var test = factory<Cat, Dog, { Dog(): Dog, Cat(): Cat }>(cat, dog);

var d = test.Dog(); // no error
var c = test.Cat(); // no error

(code in playground)