Home > Enterprise >  how to create a type safe custom hook?
how to create a type safe custom hook?

Time:09-22

I'm calling a custom function createUser but I can pass numbers and not strings and it doesn't error. Equally, I can forget an argument and it still doesn't give me the red squiggles

      const [userState, createUser] = useCreateUser();
      ...
      <div
        onClick={(): void => {
          createUser({
            email: '[email protected]',
            name: 'test1',
            password: 'topSecret!',
            username: 'testuser1',
          });
        }}
      >
        createUser
      </div>

the function looks like

import { useState } from 'react';

interface CreateUserShape {
  email: string;
  name: string;
  password: string;
  referrersCode: string;
  username: string;
}

const useCreateUser = (initialState = {}): any => {
  const [state, setState] = useState(initialState);

  const createUser = async (user: CreateUserShape): Promise<void> => {
    if (user.email && user.password) {
      const method = 'POST';
      const redirect = 'follow';
      const headers = new Headers();
      const body = JSON.stringify(user);
      const url =
        'https://my-fancy-app.ondigitalocean.app/api/v1/onboarding/createUser';
      headers.append('Content-Type', 'application/json');
      const res = await fetch(`${url}`, {
        method,
        headers,
        redirect,
        body,
      });
      const response = await res.json();
      setState({ response });
    }
  };

  return [state, createUser];
};
export { useCreateUser };

How do I get the custom hook to enforce that only strings can be passed to it?

CodePudding user response:

Your useCreateuser function is returning any which is going to allow anything to be returned. const useCreateUser = (initialState = {}): any => {}. Here you could just state the types that you want in your 2 returned values and you should get your desired result. So you can do something like the following:

type UseCreateUser = [
  state: any, // or state what type this should be
  createUser: (user: CreateUserShape) => Promise<void>
]

and then set that as your return type for the useCreateUser() like so:

const useCreateUser = (initialState = {}): UseCreateUser => {
  const [state, setState] = useState(initialState);

  const createUser = async (user: CreateUserShape): Promise<void> => {
    if (user.email && user.password) {
      const method = 'POST';
      const redirect = 'follow';
      const headers = new Headers();
      const body = JSON.stringify(user);
      const url =
        'https://my-fancy-app.ondigitalocean.app/api/v1/onboarding/createUser';
      headers.append('Content-Type', 'application/json');
      const res = await fetch(`${url}`, {
        method,
        headers,
        redirect,
        body,
      });
      const response = await res.json();
      setState({ response });
    }
  };

  return [state, createUser];
};
  • Related