#Type Help

38 messages · Page 1 of 1 (latest)

charred tendon
#
interface AuthContextTypeAuthenticated {
  authStatus: "AUTHENTICATED";
  user: User;
}

interface AuthContextTypeUnAuthenticated {
  authStatus: "NOT_AUTHENTICATED" | "FETCHING";
  user: undefined;
}

interface AuthContextType extends AuthContextTypeAuthenticated, AuthContextTypeUnAuthenticated {
  login: (user: User) => void;
  logout: () => void;
}

i'm looking to produce something like this, but extends doesn't. i don't want to do AuthContextTypeAuthenticated extends ...

hardy crystal
#

not sure what exactly "something like this" is, but i assume it's something like this?

type AuthContextType = {
  login: (user: User) => void;
  logout: () => void;
} & (AuthContextTypeAuthenticated | AuthContextTypeUnAuthenticated);
#

you could just have the 2 interfaces be part of a discriminated union

charred tendon
#

yes that is probably what i'm looking for!

hardy crystal
#

also to explain; extends is an intersection, you inherit everything the supertype defines.
you're inheriting authStatus from both supertypes, and they conflict

charred tendon
#

i tried using &, but i did use it properly i guess

#

ty for the explanation and help

#

i was stuck for a while

hardy crystal
#

i think the 2 separate interfaces for Authenticated/UnAuthenticated is kinda unnecessary tbh

#

they don't seem very useful outside of just constructing AuthContextType

charred tendon
#

i do have it used in one other place which is why wanted this

hardy crystal
#

although if you are using them elsewhere, you should have the latter be Unauthenticated as a single word

charred tendon
#
  const [auth, setAuth] = useState<
    | {
        authStatus: "AUTHENTICATED";
        user: User;
      }
    | {
        authStatus: "NOT_AUTHENTICATED" | "FETCHING";
        user: undefined;
      }
  >({
    authStatus: "FETCHING",
    user: undefined,
  });

i had them as separate states and TS was complaining so i combined them and now i need a type to use so i don't duplicate code!

hardy crystal
charred tendon
#

ok let me see it again

#

AuthProvider.ts

  const [authStatus, setAuthStatus] = useState<AuthStatus>("FETCHING");
  const [user, setUser] = useState<User>();

  return (
    <AuthContext.Provider
      ERROR HERE -> value={{
        authStatus,
        user,
        login: loginHandler,
        logout: logoutHandler,
      }}
    >
      {children}
    </AuthContext.Provider>
  );

Error

TS2322: Type '{ authStatus: "AUTHENTICATED" | "NOT_AUTHENTICATED"; user: User | undefined; login: (user: User) => void; logout: () => void; }' is not assignable to type 'AuthContextType'.   Type '{ authStatus: "AUTHENTICATED" | "NOT_AUTHENTICATED"; user: User | undefined; login: (user: User) => void; logout: () => void; }' is not assignable to type '{ login: (user: User) => void; logout: () => void; } & UnauthenticatedUser'.     Type '{ authStatus: "AUTHENTICATED" | "NOT_AUTHENTICATED"; user: User | undefined; login: (user: User) => void; logout: () => void; }' is not assignable to type 'UnauthenticatedUser'.       Types of property 'authStatus' are incompatible.         Type '"AUTHENTICATED" | "NOT_AUTHENTICATED"' is not assignable to type '"NOT_AUTHENTICATED" | "FETCHING"'.           Type '"AUTHENTICATED"' is not assignable to type '"NOT_AUTHENTICATED" | "FETCHING"'. Did you mean '"NOT_AUTHENTICATED"'?
#

the type of value is the AuthContextType you showed me above

hardy crystal
#

looks like AuthStatus isn't accounting for "FETCHING", for one?

#

but also more generally, the issue is probably because you have authStatus and user coming from different sources, they aren't guaranteed to be aligned

#

authStatus could be "AUTHENTICATED" while user is undefined

charred tendon
#

okay that's why i ended up combining it! i have this type export type AuthStatus = "AUTHENTICATED" | "NOT_AUTHENTICATED" | "FETCHING"; with the status. is there a way to use it in this code or my two interfaces

type AuthContextType = {
  login: (user: User) => void;
  logout: () => void;
} & (AuthContextTypeAuthenticated | AuthContextTypeUnAuthenticated);
hardy crystal
#

not really? but you could derive AuthStatus as AuthContextType['authStatus']

#

but also you're missing the point

hardy crystal
#

everything checks out

charred tendon
#

🙂 cool

hardy crystal
#

i had them as separate states
yep that definitely says separate types brain 🙃

charred tendon
#

oh wait

#

i think i get it

#

i get all the possible values from AuthContextType['authStatus`] and use it as my status?

hardy crystal
#

yeah

#

because if you specify them separately, and you change one, you might forget to change the other and that can cause issues
it's a form of future proofing
alternatively you could have AuthStatus be an enum and use that in AuthContextType

charred tendon
#

i know what you mean, but i don't know the syntax for it. i'm also a bit scared to use enum. i'm not familiar enough with TS enums and they seem scary to me

hardy crystal
#

the basic idea is to have a single source of truth for any given thing

#

!hb indexed access

onyx agateBOT
hardy crystal
#

it's this ^