Sebastien Lorber
Sebastien Lorber

Reputation: 92120

Typescript typing for method array argument spread

I'd like to design a library that wraps any async function. The wrapped async function can have multiple args

If I do

type AsyncFunction<I, O> = (inputs: I) => Promise<O>;

function wrapper<I, O>(
  asyncFunction: AsyncFunction<I, O>,
): AsyncFunction<I, O> { ... }

The typing of T will only apply to the first arg so this makes my wrapper unusable with any async function that takes multiple parameters.

Can someone give me a solution to support multiple args?

enter image description here

Edit

This is where I am currently:

type AsyncFunction<I extends any[], O> = (...inputs: I) => Promise<O>;

export function onlyResolvesLast<I extends any[], O>(
  asyncFunction: AsyncFunction<I, O>,
): AsyncFunction<I, O> {
  let cancelPrevious;
  return function wrappedAsyncFunction(...args) {
    cancelPrevious && cancelPrevious();
    const initialPromise = asyncFunction(...args);
    const { promise, cancel } = createImperativePromise(initialPromise);
    cancelPrevious = cancel;
    return promise;
  };
}

enter image description here

Upvotes: 0

Views: 234

Answers (2)

Sebastien Lorber
Sebastien Lorber

Reputation: 92120

I have found the solution I was looking for in existing typedefs:

// Type definitions for debounce-promise 3.1
// Project: https://github.com/bjoerge/debounce-promise
// Definitions by: Wu Haotian <https://github.com/whtsky>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
// TypeScript Version: 3.0

declare namespace debounce {
    interface DebounceOptions {
        leading?: boolean;
        accumulate?: boolean;
    }
}

type ArgumentsType<T> = T extends (...args: infer A) => any ? A : never;

declare function debounce<T extends (...args: any[]) => any>(
    func: T,
    wait?: number,
    options?: debounce.DebounceOptions
): (
    ...args: ArgumentsType<T>
) => ReturnType<T> extends Promise<any>
    ? ReturnType<T>
    : Promise<ReturnType<T>>;

export = debounce;

Upvotes: 0

Titian Cernicova-Dragomir
Titian Cernicova-Dragomir

Reputation: 249506

If you want to support multiple parameters you need to use tuples in rest parameters:

type AsyncFunction<I extends any[], O> = (...inputs: I) => Promise<O>;

function wrapper<I extends any[], O>(
asyncFunction: AsyncFunction<I, O>,
): AsyncFunction<I, O> { return asyncFunction }

async function fn(a: number, b: number) {
    return 1;
}

wrapper(fn)(1, 2)

Upvotes: 2

Related Questions