0

I have set a context that distributes Firebase auth objects like this:

export function AuthProvider(props: {children: React.ReactNode}) {
    const [user, setUser] = useState<IUser>({uid: ""});

    useEffect(() => {
        const unsubsribe = firebaseApp.auth().onAuthStateChanged(user => {
            if (user) {
                setUser(user);
                console.log("user: " + user.uid);
            }
        });
        return () => {
            unsubsribe();
        }
    }, [user]);

    const authContextValue = {
        firebaseApp,
        user,
        signOut: () => firebaseApp.auth().signOut(),
        signIn: (email: string, password: string) => firebaseApp.auth().signInWithEmailAndPassword(email, password),
    };

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

export const useAuth = () => React.useContext(AuthContext);

I try to consume the passed objects like this:

const {user} = useAuth();
    const {signOut} = useAuth();

Which results in this error: Error:(17, 12) TS2339: Property 'user' does not exist on type '{}'.

I know that the context is providing the objects (it was working in plain JS, before transformation of consumer component to TS) - so why does TypeScript think that only {} (empty object) is passed? What is the proper pattern for using useContext hook with TypeScript?

Faire
  • 706
  • 1
  • 9
  • 31

1 Answers1

6

Create an interface and assign it to your hook:

interface AuthContextType {
  user: IUser;
  signOut: () => void;
  signIn: () => void;
}

export const useAuth = () => React.useContext(AuthContext) as AuthContextType;

Here is a small codesandbox to check it out. Also read more about using Typescript with the Context Api here.

Gh05d
  • 7,923
  • 7
  • 33
  • 64