使用 Object.keys() 时保留类型

Preserving type when using Object.keys()

我有一个带有键入键的对象,我们称它们为状态 (StatusesType)。 我需要遍历对象并将键传递给某些需要相同类型 StatusesType 参数的方法,让它成为 statusPrinter()

type StatusesType = 'PENDING' | 'APPROVED' | 'REJECTED';
type SomeMap = {
    [key in StatusesType]?: number
}

const STATUSES: SomeMap = {
    PENDING: 5,
    REJECTED: 2,
};

function statusPrinter(val: StatusesType) {
    console.log('- ', val);
}

Object.keys(STATUSES).forEach(status => {
    statusPrinter(status);
});

但是当我调用 statusPrinter(status); TypeScript returns 这个错误

error TS2345: Argument of type 'string' is not assignable to parameter of type 'StatusesType'.

如何传递这种密钥保留类型?

我知道我可以用这个 statusPrinter(<StatusesType>status); 强制 TS,但我认为这是我应该做的最后一件事,我更喜欢本机解决方案。

更新: 如果无法使用 Object.keys() 保留类型迭代对象键 - 我有什么选择?有没有一种方法可以完全迭代保留类型的键,如果是这样——哪种方法最好?我没有固定 Object.keys() 但我想保留原始对象结构。

谢谢!

Object.keys 将 return 键数组,键的类型为字符串。

所以 Object.keys 的签名将是 key(object: {}): Array<string>。因此,当您遍历键时,status 是字符串类型而不是 StatusesType.

您可以将类型转换为 statusPrinter(status as StatusesType)

引用Link:

使用内置 ES2015 的简短类型安全解决方案 Map class:

type StatusesType = 'PENDING' | 'APPROVED' | 'REJECTED';

const STATUSES = new Map<StatusesType, number>([
    ['PENDING', 5],
    ['REJECTED', 2],
]);

function statusPrinter(val: StatusesType) {
    console.log('- ', val);
}

STATUSES.forEach((_, status) => statusPrinter(status));

您可以像这样使用迭代器来做到这一点:

function iterator<M, K extends keyof M>(map: M, cb: (key: keyof M, value: M[K]) => void) {
  Object.keys(map).forEach((key: K) => cb(key, map[key]))
}

iterator(STATUSES, status => {
    statusPrinter(status);
});