0

Hello so i'm new to typescript react and currently trying to make applications using typescript and tutorial from youtube.

const RegisterCustomer: React.FC = () => {
    const [text, setText] = useState<string>('');

    const [email, setEmail] = useState<string>('');
    const [username, setUsername] = useState<string>('');
    const [password, setPassword] = useState<string>('');
    const [isSubmitting, setIsSubmitting] = useState(false);
    const { register } = useAuth();
    

  return (
   <IonPage>
        <Register />
        <IonContent className="body">
        <IonGrid className="gridinput1">
        </IonGrid>

        <IonGrid className="gridinput2">
        <IonRow>
            <IonInput type="email" className="inputEmail" value={email} placeholder="Email" onIonChange={e => setEmail(e.detail.value!)}></IonInput>
        </IonRow>
        </IonGrid>
        <IonGrid className="gridinput3">
        <IonRow>
            <IonInput type="password" className="inputEmail" value={password} placeholder="Password" onIonChange={e => setPassword(e.detail.value!)}></IonInput>
        </IonRow>
        </IonGrid>
        <IonGrid className="gridinput1">
        <IonRow>
            <IonButton onClick={async e =>{
                e.preventDefault()
                const res = await register(email, password);
                if(res) {
                    console.log(res);
                }
                else {
                    //handle null response
                }
                console.log(email, password)
            }} className="buttonLogin" expand="block" size="default" color="new">
                Register Now
            </IonButton>
        </IonRow>
        </IonGrid>   
            <p className="loginSeller"><a href="https://www.w3schools.com/">Are you a seller? Login as Seller</a></p>
    </IonContent>
    </IonPage>
  );
};

export default RegisterCustomer;

and this is the authContext

type ButtonProps = {
    children: ReactNode;
    
}

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

type AuthContextType = {
    currentUser: null;
    register: (
      email: string,
      password: string
    ) => Promise<UserCredential | undefined>;
  };

const AuthContext = createContext<Partial<AuthContextType>>({}); // Partial

export default function AuthContextProvider( { children}  : ButtonProps){
    const [currentUser, setCurrentUser] = useState(null);

    function register(email: string, password:string) {
        return createUserWithEmailAndPassword(auth, email, password)
    }
    
    const value = {
        currentUser,
        register,
    }
    
    return <AuthContext.Provider value={value}>
        {children}
    </AuthContext.Provider>
}

im trying to get the data from register to firebase but i encounter error " Cannot invoke an object which is possibly 'undefined'. " in register.then in RegisterCustomer page. How do i solve this problem

5
  • 1
    Well you have declared the context type to be a Partial<AuthContextType> which means all the properties are optional and might be undefined. What would make sense, for your use case, if the register function was missing from the context? Or if you feel that register should always be present, use a type which keeps that property marked as required. Eg: Partial<Omit<AuthContextType, "register">> & Pick<AuthContextType, "register">. Commented Jun 1, 2022 at 19:55
  • can you give example how to make it right Commented Jun 1, 2022 at 20:10
  • The solution depends on if register should always be part of the context or not. If it can be missing, we will conditionally call it to avoid invoking it if it is undefined. If it cannot be missing, we have to adjust the types you are using for the context to show that it is always present. So, which is the case? Is register always part of the context, or not? (from your code it looks like you expect it to always exist, can you just confirm that is the case?) Commented Jun 1, 2022 at 20:13
  • if i change the code to const AuthContext = createContext<Partial<Omit<AuthContextType, "register">>>({}) i got error in RegisterCustomer page, it says Property 'register' does not exist on type 'Partial<Omit<AuthContextType, "register">>' Commented Jun 1, 2022 at 20:16
  • i think its always exist Commented Jun 1, 2022 at 20:17

1 Answer 1

1

Since you expect the register property to always exist, adjust your types so that it remains as a required property:

const AuthContext = createContext<Partial<Omit<AuthContextType, "register">> & Pick<AuthContextType, "register">>({});

Here, the type is broken into two pieces. The Partial<Omit<AuthContextType, "register">> creates a type that removes the register property and marks everything else as optional. The Pick<AuthContextType, "register"> creates a type that only has the register property. We combine those together using an intersection (&) to get the final type which makes everything except register optional.


This will produce an additional error since you are passing {} as the default value, but the type indicates that a register property must be present on that context. Since it is merely the default and you overwrite it when using the provider, I would recommend passing a no-op function to it as the default register value. Eg:

const AuthContext = createContext<Partial<Omit<AuthContextType, "register">> & Pick<AuthContextType, "register">>({register: async () => undefined});
Sign up to request clarification or add additional context in comments.

2 Comments

that clear the previous problem thank you, but another error occur it say Type '() => Promise<void>' is not assignable to type '(email: string, password: string) => Promise<UserCredential | undefined>'. Type 'Promise<void>' is not assignable to type 'Promise<UserCredential | undefined>'. Type 'void' is not assignable to type 'UserCredential | undefined'. is it not possible to fix this ?
I made an edit just after posting the answer which changes the default to async () => undefined instead of async () => {}. Did you try with the former version, or the latter?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.