Typescript has its problem that when you try to compare generic function to a function signature, you will run into issue.
Because for one function, it can have multi function overload. And typescript doesn't help to compare function overload to a generic function.
Instead, what we should do is compare function arguments and function return type.
import { createUser } from "fake-external-lib";
import { useState } from "react";
import { Equal, Expect } from "../helpers/type-utils";
type Mutation<TArgs extends any[], TReturn> = (
...args: TArgs
) => Promise<TReturn>;
interface UseMutationReturn<TArgs extends any[], TReturn> {
mutate: Mutation<TArgs, TReturn>;
isLoading: boolean;
}
interface UseMutationOptions<TArgs extends any[], TReturn> {
mutation: Mutation<TArgs, TReturn>;
}
export const useMutation = <TArgs extends any[], TReturn>(
opts: UseMutationOptions<TArgs, TReturn>
): UseMutationReturn<TArgs, TReturn> => {
const [isLoading, setIsLoading] = useState(false);
return {
mutate: async (...args) => {
setIsLoading(true);
try {
const result = await opts.mutation(...args);
return result;
} catch (e) {
throw e;
} finally {
setIsLoading(false);
}
},
isLoading,
};
};
const mutation = useMutation({
mutation: createUser,
});
mutation.mutate({ name: "John Doe", email: "john@doe.com" });
// @ts-expect-error email missing!
mutation.mutate({ name: "John Doe" });
mutation.mutate(
{
name: "John Doe",
email: "john@doe.com",
},
{
throwOnError: true,
// @ts-expect-error extra prop
extra: "oh dear",
}
);
type test = [
Expect<Equal<typeof mutation.isLoading, boolean>>,
Expect<
Equal<
typeof mutation.mutate,
(
user: { name: string; email: string },
opts?: {
throwOnError?: boolean;
}
) => Promise<{
id: string;
name: string;
email: string;
}>
>
>
];
- function compare Typescript arguments genericfunction compare typescript arguments typescript component function generic typescript generic reduce write typescript cleanup generic wrapper components typescript generics strongly typescript component generics react typescript inference multiple generic typescript built-in possible generic components typescript arguments passing function-like arguments included function