TypeScript 4.1 引入了template literal types,其中包括将枚举转换为其字符串表示形式。因此,您的目标可以简单地实现为:
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得到相当接近你想要的:
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,否则返回never。并且NotString<T> 返回any 是T 不是string 或更宽,否则never。通过将promoteStringToFMEvents() 中的K 约束为string & NotString<K> & Extractable<FMEvents, K>,我们说类型参数K 必须是某个字符串文字(或字符串文字的联合),FMEvents 的某些元素(或元素的联合)可以被分配到。
所以函数promoteStringToFMEvents() 将接受您期望的字符串文字(或字符串文字的联合)。该函数还通过将输入值分配给Extract<FMEvents, K> 来返回FMEvents 的关联元素,它只提取与K 匹配的FMEvents 片段。
因此,您可以编写 doSomething() 方法,使其在上面的 K 类型中是通用的,并且在该方法的实现中,您可以(如果需要)通过分配字符串将其提升为枚举到 Extract<FMEvents, K> 类型的变量。
使用doSomething() 的显式实现进行编辑:
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
}
}
希望对您有所帮助。祝你好运!