[英]How do I call a function using a generic args variable with a derived Parameters type in TypeScript?
When calling a function n
with arguments spread from a variable of type Parameters< n
>, everything seems to be in order as you might expect.当调用n
n
和 arguments 从参数类型的变量传播时,一切似乎都如您所料。 But it seems as though adding a layer of indirection throws a wrench in things, eg但是似乎添加一层间接性会引起麻烦,例如
type EventSchema = {
'performTask': (task: string, data: number) => void
};
// Mapping keys of EventSchema to arrays of listener methods
const listeners: {[p in keyof EventSchema]: EventSchema[p][]} = {
'performTask': []
};
export function emitGlobalEvent<K extends keyof EventSchema>(event: K, ...args: Parameters<EventSchema[K]>) {
listeners[event].forEach((listener) => {
listener(...args); // Error: A spread argument must either have a tuple type or be passed to a rest parameter.
});
}
When changing the ...args
type to explicitly be (task: string, data: number) => void
, no error is thrown.将...args
类型显式更改为(task: string, data: number) => void
时,不会引发错误。 It seems as though the compiler is able to infer the type correctly, and it is a tuple, so why would this error occur here?似乎编译器能够正确推断类型,并且它是一个元组,那么为什么会出现这个错误呢?
In order to assure TS that it is safe to pass ...args
to listener
, I think it worth provide your function with listeners
argument:为了确保 TS 将...args
传递给listener
是安全的,我认为值得为您的 function 提供listeners
参数:
type EventSchema = {
'performTask': (task: string, data: number) => void
};
// Mapping keys of EventSchema to arrays of listener methods
const listeners: { [p in keyof EventSchema]: EventSchema[p][] } = {
'performTask': []
};
export function emitGlobalEvent<
K extends keyof EventSchema,
Listeners extends Record<K, Array<(...args: Parameters<EventSchema[K]>) => void>>
>(listeners: Listeners, event: K, ...args: Parameters<EventSchema[K]>) {
listeners[event].forEach((listener) => {
listener(...args); // no error
});
}
emitGlobalEvent(listeners, 'performTask', 'task', 42)
Don't forget that you can curry
it:不要忘记你可以curry
它:
type EventSchema = {
'performTask': (task: string, data: number) => void
};
// Mapping keys of EventSchema to arrays of listener methods
const listeners: { [p in keyof EventSchema]: EventSchema[p][] } = {
'performTask': []
};
const withListeners = <
K extends keyof EventSchema,
Listeners extends Record<K, Array<(...args: Parameters<EventSchema[K]>) => void>>
>(listeners: Listeners,) =>
(event: K, ...args: Parameters<EventSchema[K]>) =>
listeners[event].forEach((listener) => listener(...args));
const emitGlobalEvent = withListeners(listeners)
emitGlobalEvent('performTask', 'task', 42)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.