将对象用作值中的地图键

时间:2019-05-16 14:11:59

标签: typescript

我正在尝试创建一个地图类型的对象,其中值取决于键:

export const NOTIFICATIONS: { [k: string]: { name: typeof k } } = {
    "upgrade": {
        name: "upgradexxx",
    },
};

(这会出错,因为upgradexxx不等于upgrade

我要使它成为对象的键必须与每个值上的name属性匹配。我也尝试了{[k in string]: { name: k} },但是那也不起作用。我想避免使用其他数组/类型,因为我不想重复任何事情。 NOTIFICATIONS对象应该是所有有效键的真实来源。

http://www.typescriptlang.org/play/#src=export%20const%20NOTIFICATIONS%3A%20%7B%20%5Bk%3A%20string%5D%3A%20%7B%20name%3A%20typeof%20k%20%7D%20%7D%20%3D%20%7B%0A%20%20%20%20%22upgrade%22%3A%20%7B%0A%20%20%20%20%20%20%20%20name%3A%20%22upgradexxx%22%2C%0A%20%20%20%20%7D%2C%0A%7D%3B%0A

1 个答案:

答案 0 :(得分:2)

表示这种约束的方法是在一组文字键上使用mapped type,但这需要类型本身是通用的而不是具体的。要使用泛型类型,最简单的解决方案是拥有一个帮助程序函数为您推断出泛型类型。像这样:

// enforce constraint 
const asNotifications = <T extends {
    [K in keyof T]: { name: K, [k: string]: unknown }
}>(t: T) => t;

export const BADNOTIFICATIONS = asNotifications({
    upgrade: {
        name: "upgradexxx" // error!
        // Type '"upgradexxx"' is not assignable to type '"upgrade"'.
    }
})

export const NOTIFICATIONS = asNotifications({
    upgrade: {
        name: "upgrade",
    },
    downgrade: {
        name: "downgrade",
        extraPropsAreOkay: true
    },
    lemonade: {
        name: "lemonade",
        brand: "Minute Maid"        
    }
});

NOTIFICATIONS.upgrade.name // "upgrade"
NOTIFICATIONS.downgrade.extraPropsAreOkay // boolean

希望有所帮助;祝你好运!