Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TypeScript interface default value when a property is a function type for useContext hooks

I just get started in Typescript. I seen a lot of example and question about custom hooks, but I still cant figure out due to my file structure is different with other example.

Background:

I have this 1 file named useAuth.tsx which have the structure like this:

const defaultValue = { // Here I make this temporary 1st 
  
};

const AuthContext = createContext(defaultValue)

const AuthContextProvider = (props: AuthContextProviderProps) => {
  const auth = useFirebaseAuth(); // this will use value from the hook below

  return (
    <AuthContext.Provider value={auth}>{props.children}</AuthContext.Provider>
  );
};

export default function useFirebaseAuth() {
  const [user, setUser] = useState<UserDetails | null>(null);
  const [errorMessage, setErrorMessage] = useState<string | null>(null);
  const [isLoading, setIsLoading] = useState(true);

  const loginWithEmailPassword = (email: string, password: string) => {
    //... stuff
  }

  const signUpWithEmailPassword = (email: string, password: string) => {
    //... stuff
  }

  return {
    user,
    isLoading,
    errorMessage,
    loginWithEmailPassword,
    signUpWithEmailPassword,
  };

}

**Problems:** 

So when I use this useAuth() hooks in another file, named Login.tsx like this:

const { user } = useAuth(); 

I will get this error:

Property 'user' does not exist on type '{}'.ts(2339)

My Attempts:

From my understanding, the problems is cause by user is not defined in useAuth(), therefore TypeScript doesn't know that user is existed inside useAuth

Here is what I have tried:

interface UserData {
 id: ... //etc 

}

// here define an interface for all the return value 
interface AuthContextInterface {  
  user: UserData | null;
  loginWithEmailPassword: (email: string, password: string )=> void;
  signUpWithEmailPassword: (email: string, password: string )=> void;
  isLoading: boolean;
  errorMessage: string | null;
}


// then use it here as  a type of createContext 
const AuthContext = createContext<AuthContextInterface>(defaultValue)

At this point I will get this problem at defaultValue :

Type '{}' is missing the following properties from type 'AuthContextInterface': user, loginWithEmailPassword, signUpWithEmailPassword, isLoading, errorMessage

So I have to define the value inside defaultValue as well:

const defaultValue = {
  
  user:null,
  isLoading: false,
  errorMessage: null,
  
  loginWithEmailPassword:() => void, // this is the problem, what should I put here as default value 
  signUpWithEmailPassword: () => void, 
};

Others value is not problem, but loginWithEmailPassword and signUpWithEmailPassword is a function, so as a default value what should I state, since it not exist yet?

Please give some advise. Tq

like image 483
ken Avatar asked Feb 11 '26 01:02

ken


1 Answers

try defining an empty object to defaultValue:

const defaultValue = {};

and create the context forcing the typescript to understand the defaultvalue as the interface

const AuthContext = createContext<AuthContextInterface>(defaultValue as AuthContextInterface);

if you are not using eslint, you can also do this

const AuthContext = createContext<AuthContextInterface>(defaultValue as any);
like image 158
Breno Macêdo Avatar answered Feb 13 '26 16:02

Breno Macêdo