繁体   English   中英

将泛型枚举类型作为参数传递给 Typescript 中的函数

[英]Passing generic enum type as a parameter to a function in Typescript

我有两个具有相同变体但具有不同字符串值的字符串枚举。

它们被传递给相同的初始函数,该函数接受整个枚举(我认为我可以使用typeof来做到这一点,但每个枚举应该有不同的回调。输入初始函数的最佳方法似乎是什么?

我拥有的这段代码不起作用,因为它抱怨我不能将typeof与我的T泛型参数一起使用。

enum OpsA {
    Start = 'a_start',
    Stop = 'a_stop'
}

enum OpsB {
    Start = 'b_start',
    Stop = 'b_stop'
}

type EitherOps = OpsA | OpsB

function doSomething <T extends EitherOps, U extends typeof T>(action: U, callback: (a: T) => void) {
    console.log(action.Start)
    callback(action.Start)
    console.log(action.Stop)
    callback(action.Stop)
}

// does something special for OpsA
const callbackForA = (a: OpsA) => console.log(a)
// does something else special for OpsB
const callbackForB = (b: OpsB) => console.log(b)

doSomething(OpsA, callbackForA)
doSomething(OpsB, callbackForB)

你的问题是T是一个类型而不是一个值,所以typeof T是一个类别错误。 您的困惑可能源于enum声明将命名值和命名类型都带入范围的事实,并且名称恰好相同。 但是没有一般的规则,同名的值和类型之间有任何关系。

例如, enum OpsA { /* ... */ }声明了值OpsA (具有属性键StartStop的对象)和类型OpsA (枚举对象的属性值类型的联合)。 当您将typeof OpsA编写为类型时,您在谈论枚举对象的类型,而当您将OpsA编写为类型时,您正在谈论枚举对象的属性值的类型。

但是,OpsA 类型是 OpsA 对象类型typeof OpsA OpsA属性类型这一事实不能以您可能试图做的方式概括。 没有规则说“给定类型T有一个类型typeof T其属性是类型T ”。 有关更多信息,请参阅相关问题的答案


好吧,如果你不能写U extends typeof T ,你能做什么? 您希望U成为其属性键为"Start""Stop"的对象类型。 让我们首先获取这些键的类型。 由于ObjAObjB值都有这些键,我们可以将其写为keyof typeof ObjAkeyof typeof ObjB

type OpsKeys = keyof typeof OpsA;
// type OpsKeys = "Start" | "Stop"

如果我们想说U应该是具有OpsKeys键和T类型值的对象类型,那么我们可以使用Record<K, V>实用程序类型U extends Record<OpsKeys, T> 像这样:

function doSomething<
  T extends EitherOps,
  U extends Record<OpsKeys, T>
>(action: U, callback: (a: T) => void) {
  console.log(action.Start)
  callback(action.Start)
  console.log(action.Stop)
  callback(action.Stop)
}

现在一切都在doSomething()中按预期工作。 让我们确保它也适用于调用者:

doSomething(OpsA, callbackForA) // okay
doSomething(OpsB, callbackForB) // okay
doSomething(OpsA, callbackForB) // error

看起来不错。 如果您传入不适合action参数的callback参数,编译器会发出警告。

Playground 代码链接

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM