我如何针对带有嵌套索引的现有类型创建一个强烈键入的映射文字



我想我可能正在与一个打开的错误(https://github.com/microsoft/typescript/issues/21760(相抵触,但我有效地试图弄清楚如何从其他文字常数中创建映射的字面类型。

想到以下lodash函数的正确索引键入结果。

const结果= _.mapkeys(en,x => x.display(;


export const en = {
    ACTIVE: {
        ordinal: 0,
        display: 'Active',
    },
    INACTIVE: {
        ordinal: 1,
        display: 'Inactive',
    },
} as const;
// how do i type this?
export const displayToEnum = {};
// actual runtime implementation code
for (const key in en) {
    displayToEnum[en[key].display] = en[key];
}

// What i've tried
type Displays = typeof en[keyof typeof en]['display']
type DisplayToEnum = { 
    // how do i do this dynamically - find the mapped item which fits the conditional constraint
    [P in Displays]: P extends typeof en['ACTIVE']['display'] ? typeof en['ACTIVE'] : typeof en['INACTIVE'];
}
export const displayToEnum: DisplayToEnum = {} as any;
for (const key in en) {
    displayToEnum[en[key].ordinal] = en[key];
}
// its hardcoded, but this resolves correctly to 0.
const value = displayToEnum['Active'].ordinal;

您可以使用Extract根据当前属性P

过滤en的值
export const en = {
    ACTIVE: {
        ordinal: 0,
        display: 'Active',
    },
    INACTIVE: {
        ordinal: 1,
        display: 'Inactive',
    },
} as const;
type En = typeof en
type DisplayEnum = {
    [P in En[keyof En]['display']]: Extract<En[keyof En], { display: P }>
}

或者您可以使用诸如UnionToIntersection之类的东西来构建每个成员包含一个与display

相同名称的属性的类型
type UnionToIntersection<U> = 
(U extends any ? (k: U)=>void : never) extends ((k: infer I)=>void) ? I : never
type DisplayEnum2 = UnionToIntersection<{
    [P in keyof En]: Record<En[P]['display'], En[P]>
}[keyof En]>;

最新更新