首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >获取字符串枚举的值的类型

获取字符串枚举的值的类型
EN

Stack Overflow用户
提问于 2018-06-16 08:12:50
回答 1查看 654关注 0票数 4

我有一个字符串枚举,如下所示:

代码语言:javascript
复制
export enum FMEvents {
  RECORD_ADDED = "@firemodel/RECORD_ADDED",
  RECORD_CHANGED = "@firemodel/RECORD_CHANGED",
  RECORD_MOVED = "@firemodel/RECORD_MOVED",
  RECORD_REMOVED = "@firemodel/RECORD_REMOVED",
}

我希望能够将函数的输入限制为枚举的字符串值(例如,"@firemodel/RECORD_ADDED“等)。

我想我可以只对方法signture执行以下操作:

代码语言:javascript
复制
public doSomething(event: keyof FMEvents) { ... }

但是输入都是错误的(我认为它给了我枚举对象的键,不确定,但肯定是错误的)。

然后我尝试了一下:

代码语言:javascript
复制
public doSomething(event: FMEvents) { ... }

这允许我使用FMEvents.RECORD_CHANGED调用doSomething(),但它不允许我使用doSomething("@firemodel/RECORD_CHANGED")的解析键调用它。

我正在寻找的是一种将其限制为定义为Enum中的值的字符串的方法,而不是其他的。这样,我希望上面的两个调用方法都能通过类型检查。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-06-16 08:48:41

TypeScript 4.1引入了template literal types,其中包括将枚举转换为它们的字符串表示。所以你的目标可以很简单的实现:

代码语言:javascript
复制
function doSomething(event: `${FMEvents}`) { }

doSomething("@firemodel/RECORD_CHANGED"); // okay
doSomething(FMEvents.RECORD_MOVED); // still okay

Playground link to code

TS4.1之前的答案:

TypeScript不容易将枚举值类型扩展为从中派生出的字符串或数字文字。(有一个complication that prevents using intersections to help with this)你可以使用conditional types得到你想要的东西

代码语言:javascript
复制
type Extractable<T, U> = T extends U ? any : never
type NotString<T> = string extends T ? never : any
function promoteStringToFMEvents<K 
  extends string & NotString<K> & Extractable<FMEvents, K>>(
  k: K
): Extract<FMEvents, K> {
  return k;
}

const fmAdded = promoteStringToFMEvents("@firemodel/RECORD_ADDED"); // FMEvents.RECORD_ADDED
const fmOops = promoteStringToFMEvents("@firemodel/RECORD_ADDLED"); // error

在上面的代码中,如果T或它的任何组成部分可以赋值给U,则Extractable<T, U>返回any,否则返回neverNotString<T>返回any is T is And string or wider,否则返回never。通过将promoteStringToFMEvents()中的K约束为string & NotString<K> & Extractable<FMEvents, K>,我们表示类型参数K必须是某个字符串文字(或字符串文字的并集),FMEvents的某些元素(或元素的并集)可以赋值给它。

因此,函数promoteStringToFMEvents()将接受您期望的字符串文字(或字符串文字的联合)。该函数还通过将输入值赋值给Extract<FMEvents, K>来返回FMEvents的相关元素,这将仅提取那些与K匹配的FMEvents片段。

因此,您可以编写doSomething()方法,使其在上面的K类型中是泛型的,并且在该方法的实现中,您可以(如果需要)通过将其赋给Extract<FMEvents, K>类型的变量来将字符串提升为枚举。

使用doSomething()的显式实现进行编辑

代码语言:javascript
复制
class Blomp {
  public doSomething<K
    extends string & NotString<K> & Extractable<FMEvents, K>>(k: K) {
    // k is of some subtype of "@firemodel/RECORD_ADDED" | 
    // "@firemodel/RECORD_CHANGED" | "@firemodel/RECORD_MOVED" |
    // "@firemodel/RECORD_REMOVED"

    // if you need to interpret k as a subtype of FMEvents, you can:
    const kAsFMEvent: Extract<FMEvents, K> = k;

    // or even wider as just FMEvents
    const fmEvent: FMEvents = kAsFMEvent;

    // do what you want here
  }
}

希望这能有所帮助。祝好运!

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50884025

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档