Home > Net >  Extending a type for a custom hook
Extending a type for a custom hook

Time:09-01

I have created a custom hook like this:

export const useCreateAccount: UseCreateAccountOutputs = () => {
     ...

     return { error, loading, createAccount };
};

And I can correctly create the type like this:

type CreateAccountFn = () => Promise<void>;
type UseCreateAccountOutputs = () => {
    loading: boolean;
    error: string | null;
    createAccount: CreateAccountFn;
};

However, I've created multiple custom hooks and don't want to repeat this all the time:

loading: boolean;
error: string | null;

I want to be able to create a type that extends this type:

export type CustomGraphqlHookOutputs = () => {
    loading: boolean;
    error: string | null;
};

How can I get this to work? I have tried this:

type UseCreateAccountOutputs = CustomGraphqlHookOutputs &
    (() => {
        createAccount: CreateAccountFn;
    });

And this:

type UseCreateAccountOutputs = () => {
    ...CustomGraphqlHookOutputs,
    createAccount: CreateAccountFn;
};

But neither work. Can someone let me know what I'm doing wrong?

CodePudding user response:

You can't merge the return values of function types like this. What you want to do is merge raw types and just type the return value instead of trying to type the entire function type.

export type CustomGraphqlHookOutputs = {
    loading: boolean;
    error: string | null;
};

That way you can merge it like:

type UseCreateAccountOutputs = CustomGraphqlHookOutputs & {
  createAccount: CreateAccountFn;
};

and declare the hook like:

export const useCreateAccount = (): UseCreateAccountOutputs => {
  ...

  return { error, loading, createAccount };
};

CodePudding user response:

Issue

I don't think you want CustomGraphqlHookOutputs to be a function, you want it to be the return type of the function, not the type of being a function.

In other words, instead of

export const useCreateAccount: UseCreateAccountOutputs = () => {
   ...

   return { error, loading, createAccount };
};

You want

export const useCreateAccount = (): UseCreateAccountOutputs => {
   ...

   return { error, loading, createAccount };
};

Notice where the UseCreateAccountOutputs type is moved to. Instead of typing the useCreateAccount hook it's now typing the hook's return value.

Solution

I suggest:

type CreateAccountFn = () => Promise<void>;

type CustomGraphqlHookOutputs = {
  loading: boolean;
  error: string | null;
};

type UseCreateAccountOutputs = CustomGraphqlHookOutputs & {
  createAccount: CreateAccountFn;
};

...

const useCreateAccount = (): UseCreateAccountOutputs => {
  ...

  return { error, loading, createAccount };
};
  • Related