user8758206
user8758206

Reputation: 2191

Extending a type for a custom hook

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?

Upvotes: 1

Views: 679

Answers (2)

Drew Reese
Drew Reese

Reputation: 202686

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 };
};

Upvotes: 1

Xetera
Xetera

Reputation: 1479

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 };
};

Upvotes: 2

Related Questions