最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Dynamic TypeScript Typing - Stack Overflow

programmeradmin2浏览0评论

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

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
Share Improve this question edited Dec 1, 2016 at 16:35 user210757 asked Dec 1, 2016 at 15:38 user210757user210757 7,38618 gold badges74 silver badges121 bronze badges 2
  • I have a feeling that we are missing your real use-case here. Is this code really representative for what you want to do? Are you just using dynamic object properties in this example as a way to achieve what you really want, or is dynamic properties really your main interest here? – Alex Commented Dec 1, 2016 at 16:42
  • You could just use Javascript – Brian Ogden Commented Nov 28, 2023 at 17:09
Add a comment  | 

2 Answers 2

Reset to default 11

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)


Edit

You can't "reflect" types because they don't exist in runtime, but you can use the constructor.name of the passed in instances, so you can simply do this:

class example<A, B> {
    constructor(a: A, b: B) {
        this[a.constructor.name] = function() { return a; };
        this[b.constructor.name] = function() { return b; }
    }
}

class Cat {}

class Dog {}

var cat = new Cat();
var dog = new Dog();


function factory<A, B, 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();
var c = test.Cat();

(code in playground)

You need to cast it to any object type if you wan't "JavaScript behavior" in TypeScript.

There are two syntax types, which are equivalent:

const d = (<any>test).Dog();
const c = (<any>test).Cat();

and

const testAny = test as any;
const d = testAny.Dog();
const c = testAny.Cat();

the last one was created for support in tsx files, where wouldn't work and is now the recommended way.

There is hardly an other way to do that other than use the indexer, since the properties are dynamic and not typed.

BTW I encourage to use const and let instead of var.

发布评论

评论列表(0)

  1. 暂无评论