简体   繁体   English

如何在 TypeScript 中使用具有派生参数类型的通用 args 变量调用 function?

[英]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)

Playground 操场

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)

Playground 操场

暂无
暂无

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

相关问题 如何在 Typescript 中定义和调用通用 function 参数? - How do I define and call a generic function parameter in Typescript? 如何在打字稿中键入参数为“ any”或“ void”的函数? - How do I type a function with parameters as `any` or `void` in typescript? 如何使用TypeScript向通用函数添加属性? - How do I add a property to a generic function using TypeScript? 如何在 Typescript 中定义通用变量? - How do I define a generic variable in Typescript? 如何创建一个泛型 typescript 类型 function 并从参数类型推断出返回类型? - How do I make a generic typescript type function that has the return type inferred from the argument type? 具有可变数量参数的函数的通用打字稿 - Typescript generic for function with a variable number of parameters 具有特定泛型类型参数的泛型 function 的参数类型,在 typescript - Parameters type of a generic function with specific generic type argument, in typescript TypeScript:在通用约束中使用类型参数 - TypeScript: Using Type Parameters in Generic Constraints 如何使TypeScript正确键入对泛型函数的检查调用,然后依次调用具有泛型类型参数的函数? - How can get TypeScript to correctly type check call to a generic function that in turns calls a function with a generic type parameter? 如何从 HTML 调用 Typescript 函数(使用 Parcel)? - How do I call a Typescript function from HTML (using Parcel)?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM