I have an interface which defines the function signature of various functions
interface AndroidInterface {
getXo: () => string | null;
getOx: () => string | null;
saveXo: (xo: string) => void;
saveOx: (ox: string) => void;
getGaid: () => string | null;
sendAnalyticsEvents: (
eventName: string,
eventProperties: Record<string, unknown>
) => void;
getAppVersionCode: () => number | null;
getClientId: () => string | null;
getConfig: () => Record<string, unknown> | null;
isFirstAppLogin: () => boolean;
logout: () => void;
openWhatsapp: (message: string, phone: string) => void;
}
These are basically methods on the androidInterfaceMethods
object on window
exposed through JS bridge. Meaning:
interface Window{
androidInterfaceMethods?: AndroidInterface;
}
Now, I have a function that dynamically invokes the methods on the androidInterfaceMethods
object. The function is defined and typed as follows:
const invokeAndroidInterface = <K extends keyof AndroidInterface>(
methodName: K,
...args: Parameters<ValmoAndroidInterface[K]>
): ReturnType<AndroidInterface[K]> => {
if (typeof window !== "undefined" && window.androidInterfaceMethods) {
const method = window.androidInterfaceMethods[methodName];
if (typeof method === "function") {
return method(...args);
}
}
return null
}
But strangely, I’m getting a red squiggly underline on method(...args)
with the message:
A spread argument must either have a tuple type or be passed to a rest parameter.
I’d ideally not want to assert window.androidInterfaceMethods[methodName];
and would instead want TS to infer the function signature correctly. I tried using type guards, but that didn’t help either.
As an experiment, when I hover over the method
variable, the type is AndroidInterface[K]
which is as expected. Further to verify, I hardcoded the method name, e,g:
const method = window.androidInterfaceMethods["sendAnalyticsEvents"];
and now the type of the method
variable showed (eventName: string, eventProperties: Record<string, unknown>) => void;
, but that didn’t solve the issue, but finally when I asserted ...args as AndroidInterface["sendAnalyticsEvents"]
it worked as expected.
Alternatively, asserting window.androidInterfaceMethods[methodName] as Function
also fixes the issue, but I believe it is not entirely correct.
Could anyone please shed some light here?