how do i type responses from jwtdecode?

There are multiple potential points of failure here which need to be handled. Even with proper typing, you will not be able to simply assign const user: User = getUser(); because getUser will not always return a valid user. You’re already written that it returns boolean false if there is no token. There will be an uncaught error on decoding hashToken[1] if there was no space in the tokenBearer since it would have length 1 (did you mean hashToken[0]?). And, depending on the setup of your app and what getToken() does, there’s a possibility that the decoded object is something other than a User. The return type of jwt.decode says that it can return null or string in addition to a keyed object.

My personal design strategy would be to declare that getUser will either return a User or throw an Error. Then you can wrap it in a try/catch block in TopBar.

const isUser = (user: any): user is User => {
    return typeof user === "object" && "uid" in user && "data" in user;
}

export const getUser = (): User => {

    const tokenBearer = getToken();
    if (!tokenBearer) {
        throw new Error("no token found");
    }

    const hashToken = tokenBearer.split(' ');
    if (!hashToken[1]) {
        throw new Error("invalid token length");
    }

    const decode = jwt.decode(hashToken[1]);
    if (!isUser(decode)) {
        throw new Error("invalid token object");
    }
    return decode;
}

function Topbar() {
    try {
        const user = getUser();
        return (
            <p>{user.uid}</p>
        );
    } catch (error) {
        console.error(error);
        return null;
        // but maybe return a login component instead of null
    }
}

Playground Link

If you have multiple components which access getUser, you want to isolate the logic for catching invalid responses somewhere else and separate your display logic into components like RenderTopBar which require that a User be passed in as a prop.

In this case, we could also catch by providing a dummy user or uid variable since we are only accessing user.uid.

function Topbar() {
    let uidString = "";
    try {
        const user = getUser();
        uidString = user.uid.toString();
    } catch (error) {
        console.error(error);
    }

    return (
        <p>{uidString}</p>
    );
}

CLICK HERE to find out more related problems solutions.

Leave a Comment

Your email address will not be published.

Scroll to Top