如何创建类似 TypeScript 枚举的类型,其中多个值映射到同一个键

问题描述 投票:0回答:1

我正在尝试使用 TypeScript 将使用字符串类型的代码库的一部分转换为类似枚举的类型。问题是在某些地方字符串值略有不同。有没有办法创建一个类型,其中多个值与同一个键匹配,而不是创建两个几乎相同的类似枚举的类型?

我的尝试看起来像这样(不起作用):

const STATUS = {
    CREATED: "CREATED",
    PICKED_UP: "PICKED UP" | "PICKED_UP",
    DELIVERED: "DELIVERED" | "DEL"
} as const
type ObjectValues<T> = T[keyof T];
type Status = ObjectValues<typeof STATUS>;

我正在寻找一个可以做到这一点的解决方案:

console.log(STATUS.PICKED_UP === "PICKED UP" && STATUS.PICKED_UP === "PICKED_UP") //should be true
doThingWithStatus("PICKED_UP") //should be ok, assuming function expects a type Status input

谢谢大家!

typescript
1个回答
0
投票

如上所述,不,不可能按照您的要求进行操作。当然,当 STATUS.PICKED_UP === "PICKED UP"

false
时,你不可能让
STATUS.PICKED_UP === "PICKED_UP"
都为 true 且
 
"PICKED UP" === "PICKED_UP" 为 true。 STATUS.PICKED_UP
 是某个值,该值可以是这些字符串中的一个,也可以不是其中一个,但不能是这些字符串中的 
both。 (这可能就是为什么你在编写像 "PICKED UP" | "PICKED_UP" 这样的 value
 时遇到困难。无论如何,这是 
按位 OR 运算符,并且不会作用于字符串。而且没有运算符可以将两个字符串组合成一个字符串不知何故等于它们的both的字符串。)


相反,您似乎应该重构,以便将

STATUS

 的成员映射到字符串的 
collections 。例如,您可以使用数组,如

const STATUS = { CREATED: ["CREATED"], PICKED_UP: ["PICKED UP", "PICKED_UP"], DELIVERED: ["DELIVERED", "DEL"] } as const;
那么 

Status

 就是 
ObjectValues<typeof STATUS>elementsunion

type Status = ObjectValues<typeof STATUS>[number]; // type Status = "CREATED" | "PICKED UP" | "PICKED_UP" | "DELIVERED" | "DEL"
您的检查将是 

STATUS

 
includes
 的成员是否是其集合中的字符串之一:

console.log( STATUS.PICKED_UP.includes("PICKED UP") && STATUS.PICKED_UP.includes("PICKED_UP") ); // true


你不需要使用数组;您可以使用

Set

 或以字符串作为键的对象。


您甚至可以反转您的

STATUS

 对象,以便切换键和值,因为对象允许具有不同 
keys 的属性具有相同的 value,但反之则不然(我没有看到您建议例如, "DEL"
 出现在 
STATUS.DELIVERED
STATUS.DELETED
 中,大概您考虑的是多对一或一对多关系,而不是多对多): 

const STATUS_REV = { CREATED: "CREATED", PICKED_UP: "PICKED_UP", "PICKED UP": "PICKED_UP", DELIVERED: "DELIVERED", DEL: "DELIVERED" } as const
那么 

Status

 就是 
STATUS_REV
keys
的并集

type Status = keyof typeof STATUS_REV; // type Status = "CREATED" | "PICKED UP" | "PICKED_UP" | "DELIVERED" | "DEL"
您的检查将是前一个键是否是 

"PICKED UP"value

"PICKED_UP"
STATUS_REV
 属性:

console.log( "PICKED_UP" === STATUS_REV["PICKED UP"] && "PICKED_UP" === STATUS_REV["PICKED_UP"] ); // true

Playground 代码链接

© www.soinside.com 2019 - 2024. All rights reserved.