简体   繁体   English

如何以正确的方式在对象上动态设置属性?

[英]How can I dynamically set a property on an object in right way?

I'm using Typescript . 我正在使用Typescript I would like to know how I can dynamically set a property on an object, so that Typescript recognizes the assignment. 我想知道如何在对象上动态设置属性,以便Typescript识别分配。

For example, 例如,

class Foo {
    constructor(obj: object) {
        for (const key in obj) {
            this[key] = obj[key]
        }
    }
}

const bar = new Foo({
    x: 1,
    y: 2,
});

bar.x; // Property 'x' does not exist on type 'Foo'

What I'm trying to do: 我正在尝试做的是:

class State {
    private state: string;

    constructor (states: string[]) {
        states.forEach((x) => {
            this[x] = () => this.state = x;
        });
    }
}

const x = new State(['open', 'closed']);

x.open(); // Property 'open' does not exist on type 'State'.

Hmm, I don't think TypeScript has a good way for a static class to extend a generic type. 嗯,我认为TypeScript并不是静态类扩展通用类型的好方法。 What I mean, the following invalid TypeScript is sort of what you're asking for: 我的意思是,以下无效的 TypeScript符合您的要求:

// doesn't work
class Foo<T> extends T {
  constructor(obj: T) {
    for (const key in obj) {
      this[key] = obj[key];
    }
  }
}

So you want something like a mixin class , where you extend Foo to be a constructor of both Foo and T ... but not exactly. 因此,您需要一个诸如 mixin类的类 ,在其中您可以将Foo扩展为FooT的构造函数,但又不完全是。 Here is the best I can do: 这是我能做的最好的事情:

Create a class with a different name, _Foo , which adds all the Foo -specific methods and properties. 创建一个具有不同名称_Foo的类, _Foo将添加所有特定于Foo方法和属性。 Note that you have to assert this to be of type T in order to assign T 's properties to it: 请注意,您必须断言thisT类型,以便为其分配T的属性:

class _Foo<T> {
  constructor(obj: T) {
    for (const key in obj) {
      // assert this to be compatible with T
      (this as any as T)[key] = obj[key];
    }
  }
  // Foo-specific properties and methods go here
}

Then you can define the type Foo<T> to be both _Foo<T> and T , and assert that Foo is also an object which acts as a constructor for Foo<T> : 然后可以将类型Foo<T>定义为_Foo<T>T ,并断言Foo还是充当Foo<T>的构造函数的对象:

type Foo<T> = T & _Foo<T>;
const Foo = _Foo as { new <T>(obj: T): Foo<T> };

And now use it: 现在使用它:

const bar = new Foo({
  x: 1,
  y: 2,
});

bar.x; // okay

Does that work for you? 那对你有用吗? It might be worth mentioning that the difficulty involved here might be an indication that what you're trying to do may be better achieved in TypeScript by another design. 可能值得一提的是,此处涉及的困难可能表明您尝试执行的操作可能会通过另一种设计在TypeScript中更好地实现。 For instance, maybe Foo<T> should just have a T , instead of be one. 例如,也许Foo<T>应该只是一个T ,而不是一个。 Then you can do this in a more straightforward manner. 然后,您可以以更直接的方式执行此操作。 But that's up to you. 但这取决于你。

Hope it helps; 希望能帮助到你; good luck! 祝好运!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM