提问人:cl10k 提问时间:7/18/2022 更新时间:7/18/2022 访问量:234
Typescript:引用函数签名中的函数参数
Typescript: Refer to function argument inside the function signature
问:
如何在函数签名中引用特定的函数参数?
上面的图片是假的,只是为了演示!我通过将名称填充到另一个函数中来提供并且需要检索 arg 的一些类型信息。但是我不知道如何在函数签名中引用名称。name
arg
上下文:
我正在开发一个简单的事件管理器。您可以定义事件名称,为这些名称分配回调并触发事件。回调可以有任意数量的参数。
(下面的例子非常精简,实际实现比较复杂,比如事件可以有多个回调等)
type CallbackType = (...args: any[]) => void;
const eventRegistry: Map<string, CallbackType> = new Map();
const registerEvent = (name: string, callback: CallbackType): void => {
eventRegistry.set(name, callback);
}
const fireEvent = (name: string, ...args: any[]): void => {
eventRegistry.get(name)!(...args);
}
一些示例回调
const foo = (input: number): void => {
console.log("foo here:", input);
}
const bar = (input1: boolean, input2: string): void => {
console.log("bar here:", input1, input2);
}
事件注册和事件触发
registerEvent("someEventName", foo);
registerEvent("anotherEventName", bar);
fireEvent("someEventName", 42);
fireEvent("anotherEventName", true, "Hello World");
下面是指向打字稿 playground 的链接。
上面的实现不是类型安全的。您不会得到任何有关回调期望的参数的提示。fireEvent
所以我尝试使用打字稿参数实用程序类型:
const fireEvent = (name: string, ...args: Parameters<typeof eventRegistry.get(name)>): void => {
eventRegistry.get(name)!(...args);
}
但这让我无处可去。要正确键入 args,我首先需要将回调分配给事件,但我不知道如何引用名称。
答:
1赞
Titian Cernicova-Dragomir
7/18/2022
#1
您可以使用 for 获取函数的参数,也可以使用 spread 将参数传播回函数。您甚至可以使用泛型类型参数和索引类型从对象拼写错误中获取函数的类型:Parameters
type EventRegistry = {
someEventName: typeof foo
anotherEventName: typeof bar
}
const eventRegistry: Map<string, CallbackType> = new Map();
const fireEvent = <K extends keyof EventRegistry>(name: K, ...args: Parameters<EventRegistry[K]>): void => {
eventRegistry.get(name)!(...args);
}
fireEvent("anotherEventName", true, "") // ✅
fireEvent("anotherEventName", true, 0) // ❌
您在这里的真正问题是,它不会以任何方式在 .这意味着不知道注册了什么事件,如果我们在编译时想要这些信息,我们需要将其从寄存器调用流向调用。registerEvent
fireEvent
fireEvent
fireEvent
这是我对它的刺痛,不是一个明确的解决方案,而是一个起点:
class EventRegistry<T extends Record<string, CallbackType> = {}>{
eventRegistry: Map<string, CallbackType> = new Map();
registerEvent<K extends string, C extends CallbackType>(name: K, callback: C):EventRegistry<T & Record<K, C>> {
this.eventRegistry.set(name, callback);
return this;
}
fireEvent<K extends keyof T & string>(name: K, ...args: Parameters<T[K]>): void {
this.eventRegistry.get(name)!(...args);
}
const reg = new EventRegistry()
.registerEvent("someEventName", foo)
.registerEvent("anotherEventName", bar);
reg.fireEvent("someEventName", 42); // ✅
reg.fireEvent("anotherEventName", true, "Hello World"); // ✅
reg.fireEvent("anotherEventName", true, 0); // ❌
评论
...args
name