如何从类型化对象的键中获取索引类型?

时间:2019-07-27 11:02:48

标签: typescript keyof

我之前使用过keyof运算符来获取对象的键,但是我仍然停留在这个简单的代码上。

interface Definition { name: string; visible: boolean; itemIds: number[]; }

const Definitions: { [key: string]: Definition } =
{
    line1: { name: 'line 1', visible: true, itemIds: [1, 2, 3] },
    line2: { name: 'line 2', visible: true, itemIds: [4, 5, 6, 7] },
    next_line: { name: 'next', visible: false, itemIds: [] },
    // more items here...
    prod: { name: 'production', visible: true, itemIds: [718, 719] },
};

type DefKeys = keyof typeof Definitions; // Wrong!

我想得到的是

DefKeys = 'line1' | 'line2' | 'next_line' | 'prod'

但我实际上得到了

DefKeys = string | number

如果删除对象上的类型约束,我会得到期望的结果,但是我失去了类型安全性。

const Definitions = // No type here
{
    line1: { name: 'line 1', visible: true, itemIds: [1, 2, 3] },
    line2: { name: 'line 2', visible: true, itemIds: [4, 5, 6, 7] },
    next_line: { name: 'next', visible: false, itemIds: [] },
    // more items here...
    prod: { name: 'production', visible: true, itemIds: [718, 719] },
};

type DefKeys = keyof typeof Definitions; // correct

如何将类型保留在对象的定义上并从中获取索引类型?

1 个答案:

答案 0 :(得分:1)

您可以使用通用类型形参将定义创建包装到函数调用中,并在形参上定义约束。这样,原始对象类型将得以保留:

function getDefinitions<T extends { [key: string]: Definition }>(definitions: T): T {
    return definitions;
}

const Definitions = getDefinitions({
    line1: { name: 'line 1', visible: true, itemIds: [1, 2, 3] },
    line2: { name: 'line 2', visible: true, itemIds: [4, 5, 6, 7] },
    next_line: { name: 'next', visible: false, itemIds: [] },
    // more items here...
    prod: { name: 'production', visible: true, itemIds: [718, 719] },
});

type DefKeys = keyof typeof Definitions; // "line1" | "line2" | "next_line" | "prod"