[英]Passing generic enum type as a parameter to a function in Typescript
I have two string enums that have the same variants, but have different string values.我有两个具有相同变体但具有不同字符串值的字符串枚举。
They get passed to the same initial function, which accepts the entire enum (which I think I can do using typeof
, but each enum should have a different callback. What seems to be the best way to type the initial function?它们被传递给相同的初始函数,该函数接受整个枚举(我认为我可以使用
typeof
来做到这一点,但每个枚举应该有不同的回调。输入初始函数的最佳方法似乎是什么?
This code that I have doesn't work, as it complains that I can't use typeof
with my T
generic parameter.我拥有的这段代码不起作用,因为它抱怨我不能将
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)
Your problem is that T
is a type and not a value, so typeof T
is a category error.你的问题是
T
是一个类型而不是一个值,所以typeof T
是一个类别错误。 Your confusion probably stems from the fact that enum
declarations bring into scope both a named value and a named type, and the names happen to be the same.您的困惑可能源于
enum
声明将命名值和命名类型都带入范围的事实,并且名称恰好相同。 But there's no general rule that a value and a type with the same name have any relationship to each other.但是没有一般的规则,同名的值和类型之间有任何关系。
For example, enum OpsA { /* ... */ }
declares both the value OpsA
(an object with property keys Start
and Stop
) and the type OpsA
(a union of the types of the property values of the enum object).例如,
enum OpsA { /* ... */ }
声明了值OpsA
(具有属性键Start
和Stop
的对象)和类型OpsA
(枚举对象的属性值类型的联合)。 When you write typeof OpsA
as a type you are talking about the type of the enum object, while when you write OpsA
as a type you are talking about the type of the enum object's property values.当您将
typeof OpsA
编写为类型时,您在谈论枚举对象的类型,而当您将OpsA
编写为类型时,您正在谈论枚举对象的属性值的类型。
But the fact that the type OpsA
is the property type of the object type typeof OpsA
cannot be generalized the way you are presumably trying to do.但是,OpsA 类型是 OpsA 对象类型
typeof OpsA
OpsA
属性类型这一事实不能以您可能试图做的方式概括。 There is no rule that says "given the type T
there is a type typeof T
whose properties are of type T
."没有规则说“给定类型
T
有一个类型typeof T
其属性是类型T
”。 See an answer to a related question for more information.有关更多信息,请参阅相关问题的答案。
Okay, if you can't write U extends typeof T
, what can you do?好吧,如果你不能写
U extends typeof T
,你能做什么? You want U
to be an object type whose property keys are "Start"
or "Stop"
.您希望
U
成为其属性键为"Start"
或"Stop"
的对象类型。 Let's get a type for those keys first.让我们首先获取这些键的类型。 Since both
ObjA
and ObjB
value have these keys, we can write that as either keyof typeof ObjA
or keyof typeof ObjB
:由于
ObjA
和ObjB
值都有这些键,我们可以将其写为keyof typeof ObjA
或keyof typeof ObjB
:
type OpsKeys = keyof typeof OpsA;
// type OpsKeys = "Start" | "Stop"
If we want to say that U
should be an object type with keys of OpsKeys
and values of type T
, then we can use the Record<K, V>
utility type : U extends Record<OpsKeys, T>
.如果我们想说
U
应该是具有OpsKeys
键和T
类型值的对象类型,那么我们可以使用Record<K, V>
实用程序类型: U extends Record<OpsKeys, T>
。 Like this:像这样:
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)
}
Now everything works as desired inside doSomething()
.现在一切都在
doSomething()
中按预期工作。 Let's make sure that it also works for callers:让我们确保它也适用于调用者:
doSomething(OpsA, callbackForA) // okay
doSomething(OpsB, callbackForB) // okay
doSomething(OpsA, callbackForB) // error
Looks good.看起来不错。 The compiler warns if you pass in a
callback
argument that's inappropriate for the action
argument.如果您传入不适合
action
参数的callback
参数,编译器会发出警告。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.