github / mini-throttle

A small JavaScript throttle & debounce implementation.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Better types for the returned function

stof opened this issue · comments

Currently, the type for the throttled function are not very helpful, because arguments are unknown. But we actually know the argument signature: the same than the original function.
I looked at type declarations for other throttle implementations in the wild to compare the options:

I think a way to go would look like that:

interface Cancelable {
  cancel(): void;
}

export function throttle<T extends (...args: unknown[]) => unknown>(
  callback: T,
  wait = 0,
  {start = true, middle = true, once = false}: ThrottleOptions = {}
): ((...funcArgs: Parameters<T>) => void) & Cancelable {
  // ...
}

Being a JS user (using typescript types to run Typescript in type-checking mode on JS files and to power IDE completion), I'm not sure what are the backward-compatibility effect of changing the type of the generic. It might be a BC break for code specifying the type explicitly (i.e. throttle<SomeType>(myfunc, 10) when calling it). For people relying on type inference, there should be no BC break (unless you consider that a type failure due to a misuse of the throttled function is a BC break, when it would very likely prevent getting a runtime failure due to the wrong arguments).

What do you think about that ? Should I submit a PR ?

note that Parameters<T> requires Typescript 3.1+, so I think that's fine given its release date.

Hey @stof thanks for the issue!

Parameters<T> does indeed look very cool and I think just what we want! Happy to see a PR raised for it if you'd like to raise one!

I already have half of the patch locally to test that my proposal was accepted by the ts compier, so I will happily send a PR.

Actually, making further tests, my initial assumption was wrong. The current types are already reporting the right signature (the generic is inferred as a tuple of arguments, so exactly the same). So there is nothing to change. The only difference between the current implementation and my suggestion would be how explicit generics are written (as the generic does not refer to the same part), and that would be a useless BC break.

Thanks for investigating!