Home > Enterprise >  typescript error Cannot invoke an object which is possibly 'undefined'
typescript error Cannot invoke an object which is possibly 'undefined'

Time:06-02

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

CodePudding user response:

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});
  • Related