typescript 使用Object.keys()遍历对象

ruarlubt  于 2022-11-18  发布在  TypeScript
关注(0)|答案(1)|浏览(427)

为什么这个例子在TypeScript中不起作用:

const nationStates = ['berlin', 'hamburg'] as const
export type NationStateType = typeof nationStates[number]

export const wfsConfig: {
      [nationState in NationStateType]: Partial<Record<ElementTypes, WFSConfigurations[]>>
    } = {
      berlin: { trees: berlinTrees, parcels: berlinParcels },
      hamburg: { trees: hamburgTrees },
    }

    Object.keys(wfsConfig).forEach(states => {
      console.log(wfsConfig.berlin.parcels) // works
      wfsConfig[states] // does not work
    })

错误消息为:
元素隐式具有“any”类型,因为类型“string”的表达式不能用于索引类型“{ berlin: Partial<Record<ElementTypes, WFSConfigurations[]>>; hamburg: Partial<Record<ElementTypes, WFSConfigurations[]>>; }”。
在类型'{ berlin: Partial<Record<ElementTypes, WFSConfigurations[]>>; hamburg: Partial<Record<ElementTypes, WFSConfigurations[]>>; }'上找不到具有类型'string'参数的索引签章。
我理解(部分),但我已经(或没有?)通过以下方式键入了wfsConfig的键:

{[nationState in NationStateType]: Partial<Record<ElementTypes, WFSConfigurations[]>>}

因此TS应该知道键不仅仅是字符串,而且总是NationStateType...
我的理解问题出在哪里?或者说哪里出了问题?
非常感谢!

h4cxqtbf

h4cxqtbf1#

这是因为JS运行时不保证对象自己的键是否为类型。
如果你确定对象真的是Record或者真的只具有已知的道具,那么制作一个自定义函数:
Playground链接

/** Use this when you are sure this object is Record */
function recordEntries<K extends string, V>(t: Record<K, V>) {
  return Object.entries(t) as [K, V][];
}

/** Use this when you are precisely know own keys */
function typedEntries<T extends {}>(t: T) {
  return Object.entries(t) as { [K in keyof T]: [K, T[K]] }[keyof T][]
}

let x = typedEntries({ a: 1, b: 2, c: { d: 4 } } as const)
//  ^?


let a: { a: 1 } = { a: 1 };
let ab: { a: 1, b?: 2 } = a;
ab.b = 2;

let c = typedEntries(a)
//  ^?
console.log(c)
// > [["a", 1], ["b", 2]] 

class D {
  f(){}
  g = 0;
}
let d = new D()
//  ^?

let d1 = typedEntries(d)
//  ^?
console.log(d1)
// > [["g", 0]]

相关问题