Object.entries(qs).forEach(..) - 解决忽略类型注释的lambda问题



我有一个对象exampleMap,它实现了DictionaryNum<number>,作为键值存储。我使用一个对象,因为地图不适用于例如JSON.stringify.

interface DictionaryNum<T> {
[id: number]: T;
}
let exampleMap = {
[1]: 1,
}

有时我必须迭代整个地图,例如在函数createQsFromDict()中,并使用地图的键和值进行进一步处理。在这种情况下,我忽略了这一点,以保持示例简单。 但是,我使用Object.entries(dict).forEach()遍历地图,因为它似乎是此类任务的最佳匹配(顺序无关紧要)。

function createQsFromDict(dict: DictionaryNum<number>): boolean {
Object.entries(dict).forEach(
([qP, aP]: number[]) => {                           //[qP = "1", aP = 1]  "1"!=1 
if (qP === 1) {
return true
}
})
return false
}
let works = createQsFromDict(exampleMap)

问题是,尽管我使用了两次类型注释(函数参数,lambda)并且没有产生错误,但在转译时,键是一个字符串,尽管TypeScript认为它是一个数字。因此,当我在构造函数中使用它时,对象将在对象中以字符串结束。 显然,这不是我想要的。我希望隐式转换或错误。

我的问题是: 获得所需行为的最佳方法是什么*。 目前我使用parseInt(qP)并删除类型注释,但这似乎不是最佳解决方案,因为这正是我不想用 JavaScript 编码的原因。

*仍:

  • 快速访问各个值
  • 键/值的快速迭代
  • JSON.stringifyable

Object.entries(obj)生成一个[string, any]数组(或者在objT数组或值均为T的字符串键字典的情况下,可能[string, T]合适的T)。 这是因为,即使对于数组,JavaScript 实际上也会将所有索引(symbol个索引除外)转换为字符串。 因此,{"1": "hey"}{1: "hey"}是相同的值并且具有相同的类型。 TypeScript 公开number索引是为了方便处理数组和类数组对象,但从技术上讲,这是一个谎言。 事实是,数组键属于像numericString这样的类型,显然对任何人都无法处理太复杂了。

无论如何,您的问题是:为什么编译器不进行隐式转换或在forEach()回调中抛出错误?

答:TypeScript 不做隐式转换,这将违反 TypeScript 非目标 #5 关于根据类型信息发出不同的 JS 代码......类型系统在运行时之前被完全擦除。 您只需要自己将字符串转换为数字,或者使用其他一些数据结构来表示字典(例如[number, number]对数组或Map<number, number>)

至于抛出错误,这是合理的。 但是,不幸的是,any类型(又名类型系统的"逃生舱口")正在抑制这一点。 您正在获取一个预期为[string, any]类型的值,并将其视为number[]。 TypeScript 很乐意将像[A, B]这样的元组类型视为Array<A|B>。 但[string, any]可以像Array<string | any>一样对待,这是any[],也可以像number[]一样对待而毫无怨言。 这对你来说是不幸的。

若要重新获得某种类型安全性,可以通过类型断言使用其他重载Object.entries(dict)

Object.entries(dict as Record<string, number>)

这将导致Object.entries()返回一个Array<[string, number]>,并且您的代码将出错,除非您实际上将密钥视为string。 脱节的是标准库不希望有人将非数组类数字索引的东西传递给Object.entries()。 如果您使用数组(具有length属性的东西),它也会捕获错误。

所以这是一系列相当不幸的边缘情况,咬了你。 不好意思。 无论如何,希望有帮助。 祝你好运!

查看Object.entries声明:

entries<T>(o: { [s: string]: T } | ArrayLike<T>): [string, T][];

看起来entries方法默认将对象属性转换为string,您必须在回调中自行转换。

使用==代替比较器===是您的解决方案吗?

"1" === 1 // false
"1" == 1 // true

最新更新