将来自`Partial`的TS循环属性设置为`Class`。

huangapple go评论64阅读模式
英文:

TS loop properties from Partial<Class> and set it to Class

问题

我有一个基本的JS类。一个非常简化的示例如下:

class Test {
  a: number = 1;
  b: string = 'foo';

  populate(data){
    for (let i in data) {
      this[i] = data[i];
    }
  }
}

所以我基本上可以根据来自API的JSON数据填充实例。

const myClass = new Test();
myClass.populate({
  a: 3,
  b: 'hello world'
});

这一切都有效,并且已经在生产中使用了好几年(当然,包括hasOwnPropertytypeof !== 'undefined'检查等)。

我想在TypeScript中正确编写这个,但是我不知道如何做,因为一切都失败了。我尝试了很多次,但都没有成功,例如:

class Test {
    a: number = 1;
    b: string = 'B';

    populate(data: Partial<Test>){
        for(let i in data){
            const v = data[i as keyof Partial<Test>];
            if(v && Object.prototype.hasOwnProperty.call(this, i)){
                this[i as keyof Test] = v; // error Type 'string' is not assignable to type 'never'.(2322)
            }
        }
    }
}

const a = new Test();
a.populate({
    a: 2,
    b: 'bar'
});

除了使用//@ts-ignore[key: string]: any之外(我希望避免使用any),我能做些什么来使这个工作?

这是我的在线示例

英文:

I have a basic JS class. A very heavily simplified example would be

class Test {
  a: number = 1;
  b: string = &#39;foo&#39;;

  populate(data){
    for (let i in data) {
      this[i] = data[i];
    }
  }
}

So I can basically populate an instance based on JSON data from an API.

const myClass = new Test();
myClass.populate({
  a: 3, 
  b: &#39;hello world&#39;
});

This all works and is used in production for several years (of course with included hasOwProperty and typeof !== &#39;undefined&#39; checks and so on).

I would like to properly code this in TypeScript, but I have no idea how, because everything fails. I had so many attempts with no avail, for example:

class Test {
    a: number = 1;
    b: string = &#39;B&#39;;

    populate(data: Partial&lt;Test&gt;){
        for(let i in data){
            const v = data[i as keyof Partial&lt;Test&gt;];
            if(v &amp;&amp; Object.prototype.hasOwnProperty.call(this, i)){
                this[i as keyof Test] = v; // error Type &#39;string&#39; is not assignable to type &#39;never&#39;.(2322)
            }
        }
    }
}

const a = new Test();
a.populate({
    a: 2,
    b: &#39;bar&#39;
});

What could I do except a //@ts-ignore and [key: string]: any (I would like to omit anys) to make this working?
Here is my playground

答案1

得分: 2

class Test {
    populate(data: Partial&lt;Test&gt;) {
        Object.assign(this, data);
    }
}

编辑:

在你描述的情况下,你可以尝试:

for (const [key, value] of Object.entries(data)) {
    if(this.hasOwnProperty(key)) {
        Object.assign(this, { [key]: value });
    }
}

更好的解决方案可能是查看验证库,比如zod,这样你可以在代码中较早地捕获这种错误,而不是在达到populate函数之前。

英文:

How about this 将来自`Partial<Class>`的TS循环属性设置为`Class`。

class Test {
    populate(data: Partial&lt;Test&gt;) {
        Object.assign(this, data);
    }
}

EDIT:

In the case you described, you can try:

for (const [key, value] of Object.entries(data)) {
    if(this.hasOwnProperty(key)) {
        Object.assign(this, { [key]: value });
    }
}

The better solution might be to look into validation libraries, such as zod, so that you can catch that sort of error earlier in your code, before it reaches the populate function.

huangapple
  • 本文由 发表于 2023年3月7日 19:41:07
  • 转载请务必保留本文链接:https://go.coder-hub.com/75661525.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定