我有一个像这样的枚举:
export enum ApiFunctions {
"setHidden" = "HIDE",
"setReadOnly" = "SET_READ_ONLY",
"setVisible" = "SHOW",
"setDescription" = "SET_DESCRIPTION",
"setName" = "SET_NAME",
"makeRequest" = "MAKE_REQUEST"
}
今天早些时候,我从这个枚举中创建了一个新类型,如下所示:export type ApiActions = Exclude<`${ApiFunctions}`, "MAKE_REQUEST">
此类型返回键的所有值,除了“MAKE_REQUEST”(SET_DESCRIPTION,....)问题是模板文字类型是在 ts 4.1 上发布的,当前 bundler 的 ts 版本是 3.9.7,我无法真正更新它,因为它是外部提供的。
我尝试通过执行以下操作来复制这种类型:
export type Something = Exclude<typeof ApiFunctions[keyof typeof ApiFunctions], "MAKE_REQUEST">
但是这种类型并没有给我每个键的实际字符串值 SET_NAME | SET_DESCRIPTION ...
在 ApiFunctions.setName | ApiFunctions.setDescription ...
的行中给了我一些东西有没有办法以任何其他方式实现模板文字创建的完全相同的类型?
最佳答案
不,在 TypeScript 4.1 之前没有编程方式来扩大 string enum
types到他们对应的string literal types .
但是,您可能不应该做这样的事情(即使使用 TypeScript 4.1 及更高版本)并且可能有更好的方法。 typescript enum
s 最适合它们的值对您的 TypeScript 代码库不透明的情况。所以除了 enum
定义本身,你的代码不应该关心它们的具体值。访问这些值的唯一方法是通过枚举。所以总是ApiFunctions.setHidden
永远不会"HIDE"
.
这意味着您应该能够更改这些值,并且 TypeScript 代码中的任何内容都不会中断。当然,如果这些值对某些外部系统(如 API)很重要,那么与该系统的通信将不再有效。但反过来,如果外部系统发生变化,它想要 "CONCEAL"
而不是 "HIDE"
,您唯一需要更改的 TS 代码是 setHidden = "CONCEAL"
;您不需要对 "HIDE"
进行全局查找和替换带有 "CONCEAL"
的字符串文字文字。
毕竟,正如您所见,编译器并不容易引用枚举的文字值。它认为ApiFunctions.setHidden
比 "HIDE"
更具体,因此不能使用 "HIDE"
类型的值其中 ApiFunctions.setHidden
类型的值是必须的。与编译器斗争以从另一个产生一个是为了可疑的好处而付出的很多努力。如果可能的话,让枚举保持枚举。
考虑到这一点,我对 ApiActions
的建议将会:
export enum ApiFunctions {
setHidden = "HIDE",
setReadOnly = "SET_READ_ONLY",
setVisible = "SHOW",
setDescription = "SET_DESCRIPTION",
setName = "SET_NAME",
makeRequest = "MAKE_REQUEST"
}
export type ApiActions = Exclude<ApiFunctions, ApiFunctions.makeRequest>;
/* type ApiActions = ApiFunctions.setHidden | ApiFunctions.setReadOnly |
ApiFunctions.setVisible | ApiFunctions.setDescription | ApiFunctions.setName */
另一方面,如果您的 TypeScript 代码确实关心特定的字符串文字类型,那么
enum
可能不适合您的用例。自从 TypeScript 3.4 引入 const
assertions , 很容易得到 an enum-like object .它看起来像这样:export const ApiFunctions = {
setHidden: "HIDE",
setReadOnly: "SET_READ_ONLY",
setVisible: "SHOW",
setDescription: "SET_DESCRIPTION",
setName: "SET_NAME",
makeRequest: "MAKE_REQUEST"
} as const;
从此您可以通过编程方式制作 union type也称为 ApiFunctions
:export type ApiFunctions =
typeof ApiFunctions[keyof typeof ApiFunctions];
这两个定义的行为类似于 ApiFunctions
的枚举版本。 ,除了现在编译器允许您通过枚举和文字类型引用值:export type ApiActions = Exclude<ApiFunctions, "MAKE_REQUEST">;
/* type ApiActions = "SET_NAME" | "HIDE" | "SET_READ_ONLY" | "SHOW" | "SET_DESCRIPTION" */
哪种方法(如果有)更适合您,取决于您的用例。我倾向于避免
enum
s 尽我所能,因为它们不是 JavaScript 的一部分,而且它们有令人惊讶的行为(尤其是数字枚举)。但这是个人喜好。Playground link to code
关于javascript - 模板文字类型等效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72361195/