javascript - 模板文字类型等效

标签 javascript typescript types bundler template-literals

我有一个像这样的枚举:

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/

相关文章:

javascript - 为什么 escodegen 和 esprima 会在我的源代码上生成括号包装器?

javascript - 多个提交按钮仅首先初始化 javascript

c - 是否可以在运行时使用宏或任何其他功能来访问具有相同成员的不同结构?(结构更新))

javascript - 具有常量字符串和依赖类型的流类型

typescript - 如何使用Firebase模拟器pubsub在本地测试定时功能?

typescript - 使用字符串访问 TypeScript 可选对象属性

javascript - 想要一个 100% 宽度/高度的 iPhone/iPad/iOS 网页

javascript - jQuery 模板 - 将数据关联到模板 DOM 元素

typescript - TypeScript 是否难以使用泛型进行索引?

javascript - 更改嵌套对象的引用是否正在更改对根对象的引用?