【问题标题】:How to solve TS2322 error when doing this[prop] = data[prop]?执行 this[prop] = data[prop] 时如何解决 TS2322 错误?
【发布时间】:2020-11-07 19:20:02
【问题描述】:

下面的代码不起作用,我被卡住了。我该如何解决这个问题?

type Data = {
  id: number,
  name: string
}

class Person {
  id: number
  name: string

  constructor(personData: Data) {
    this.id = personData.id
    this.name = personData.name
  }

  update(updateData: Data) {
    for (const prop in updateData) {
      this[prop as keyof Data] = updateData[prop as keyof Data]
    }
  }
}

Playground link

错误:

TS2322:键入“字符串 | number' 不可分配给类型 'never'。 类型“字符串”不可分配给类型“从不”。

重要的一行在更新方法中:this[prop as keyof Data] = updateData[prop as keyof Data]。我想打字稿不知道 this[prop] 和 updateData[prop] 是同一类型(字符串|数字)。如果所有属性都是同一类型,则没有错误。但是如何告诉 typescript,它们是同一类型的呢?

【问题讨论】:

  • 这是个好问题。

标签: typescript


【解决方案1】:

似乎在这里使用组合会更好。这很容易回避您遇到的问题。

type Data = {
  id: number,
  name: string
}

class Person {
  data: Data

  constructor(personData: Data) {
    this.data = personData
  }

  update(updateData: Data) {
    this.data = updateData
  }
}

如果您真的希望能够访问 id 和 name 作为 Person 实例上的属性,您可以为它们添加 get 访问器:

get id() { return this.data.id }

get name() { return this.data.name }

Playground

【讨论】:

  • 太好了,我喜欢为此作曲(理想情况下没有访问器,因为重复)。类型安全和都可维护:向Data 添加新属性不需要更改Person。
【解决方案2】:

遗憾的是,我没有看到比断言this 可以按字符串索引更好的选择,如下所示:

(this as {[key: string]: any})[prop] = updateData[prop as keyof Data]

Playground link

for-in 循环只是让它变得过于动态而无法静态检查。


只是一个警告:声明updateData 是Data 类型只能确保它具有id: number 和name: string 属性。它不确保updateData 没有您不想复制到Person 实例的其他 属性。例如,这是对您的 update 方法的完全有效的调用:

const somePerson = new Person({id: 1, name: "Shmoe"});
const data = {id: 2, name: "Joe", update: true};
somePerson.update(data);

...当然,这会弄乱Person 的实例。 :-)

Playground link

【讨论】:

  • 你对使用更严格的类型有什么建议吗?
  • 第一次脸红,我喜欢@JLRishe's approach。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-27
  • 2018-08-04
  • 1970-01-01
  • 2020-06-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多