2

我想我可能会遇到一个带有打字稿的开放错误(https://github.com/microsoft/TypeScript/issues/21760),但我正在有效地试图弄清楚如何从其他文字常量创建映射文字类型。

从下面的 lodash 函数中考虑正确的索引类型结果。

常量结果 = _.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;
4

1 回答 1

1

您可以使用基于当前属性Extract的值来过滤enP

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]>;
于 2019-05-22T21:23:25.563 回答