I am rewriting an old browser extension in TypeScript, and came across a very hacky “convenience” function that’s intended to wrap another function to effectively “hook in” to that function. While I am going to replace this function in the production code, I was curious if it’s possible to write this in a way that satisfies TS, as my engine keeps putting up complaints.
Here’s the (subjectively) best result I’ve gotten
type GetReturnType<Type> = Type extends (...args: never[]) => infer Return ? Return : never;
type GetArgsType<Type> = Type extends (...args: infer Args) => any ? Args : never
export function wrapFunction<T, K extends keyof T>(
parent: T,
name: K,
newFunction: (
oldFn: T[K],
...args: GetArgsType<T[K]>
) => GetReturnType<T[K]>
) {
var oldFunction = parent[name]
parent[name] = (...args:GetArgsType<T[K]>) => {
return newFunction(oldFunction, ...args)
}
return parent[name]
}
With this my engine emits the following complaint at the line starting parent[name] = ...
Type '(...args: GetArgsType<T[K]>) => GetReturnType<T[K]>' is not assignable to type 'T[K]'.
'T[K]' could be instantiated with an arbitrary type which could be unrelated to '(...args: GetArgsType<T[K]>) => GetReturnType<T[K]>'.