typescript 如何在属性为混合类型的对象中动态分析对象

tcbh2hod  于 2023-01-06  发布在  TypeScript
关注(0)|答案(1)|浏览(147)

当尝试解析对象中的对象时,如下所示:

let attribute: keyof Test

for (attribute in data) {
  if (typeof data[attribute] != 'string') {
    data[attribute]['numberProperty'] = 3
  }
}

具有以下数据:

var data: Test = {
  stringProperty: "someString",
  objectProperty: {
    numberProperty: 13
  }
}

这个接口:

interface Test {
  stringProperty: string
  objectProperty: {
    numberProperty: number
  }
}

我得到了以下错误:

Element implicitly has an 'any' type because expression of type '"numberProperty"' can't be 
used to index type 'string | { numberProperty: number; }'.
  Property 'numberProperty' does not exist on type 'string | { numberProperty: number; }'.(7053)

由于这个错误抱怨字符串不能被解析为对象,我尝试通过逻辑地导出它并只允许对象通过来将其从等式中移除:

for (attribute in data) {
  if (typeof data[attribute] != 'string') { // This line is supposed to remove the string
    data[attribute]['numberProperty'] = 3
  }
}

但是,这并不奏效,我该怎么办呢?
如果你想看到错误发生的过程,这里有一个 typescript 练习场

jogvjijk

jogvjijk1#

您希望检查表达式data[attribute]narrow,检查其表观类型从联合string | { numberProperty: number }{ numberProperty: number }。但仅当键属于单个已知文本类型时,才支持对属性访问进行收缩。由于attribute本身是联合类型("stringProperty" | "objectProperty"),因此不会发生此类收缩。
microsoft/TypeScript#10530存在一个长期存在的问题,即请求支持缩小所有obj[key]表达式的范围,即使key不是单一文本类型...例如string、联合或generic。(最初的问题实际上是关于所有带括号的属性访问,但当带括号的属性是单个字符串文字时,这部分已经得到修复,所以obj["prop"]现在以obj.prop相同的方式缩小了范围,但是这个问题仍然没有解决,需要跟踪其他情况。)在不降低编译器性能的情况下做到这一点并不容易,所以这个特性仍然缺失。
除非这种情况发生变化,否则您需要解决它。建议的解决方法是,如果可能,将要缩小范围的表达式复制到它自己的变量,因为变量可以按预期缩小范围。在您的示例中,如下所示:

let attribute: keyof Test
for (attribute in data) {
  const val = data[attribute];
  if (typeof val !== 'string') {
    val['numberProperty'] = 3 // okay
  }
}

其编译没有错误,因为val确实通过检查从string | { numberProperty: number }缩小到{ numberProperty: number }
Playground代码链接

相关问题