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

时间:2017-09-15 06:42:58

标签: typescript static-typing

我有一个带有键入键的对象,我们称之为状态(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会返回此错误

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

如何传递此密钥保留类型?

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

更新:如果无法使用Object.keys()保留类型迭代对象键,我有哪些选项?有没有办法迭代保留类型的密钥,如果是这样 - 哪种方式最好?我没有修复Object.keys(),但我想保留原始对象结构。

谢谢!

3 个答案:

答案 0 :(得分:2)

Object.keys将返回一个键数组,键的类型为string。

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

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

参考链接:

答案 1 :(得分:2)

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

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));

答案 2 :(得分:1)

你可以用这样的迭代器来做到这一点:

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);
});