I have a user hook from Auth0:
const { user } = useUser();
It returns a user
object with the following types:
user: UserProfile | undefined
I am accessing the user.sub
and user.email
properties with the following types:
UserProfile.sub?: string | null | undefined
userProfile.email?: string | null | undefined
I've tried to use this object in my code like this:
<input name="userSub" type="hidden" value={user.sub} />
<input name="email" type="hidden" value={user.email} />
This returns an error that User is possibly undefined
, which I guess is because UserProfile could return undefined, so I add an ?
to the user object like this:
<input name="userSub" type="hidden" value={user?.sub} />
<input name="email" type="hidden" value={user?.email} />
This fixes that error, but value
has a red underline with the following error:
Type 'string | null | undefined' is not assignable to type 'string | number | readonly string[] | undefined'. Type 'null' is not assignable to type 'string | number | readonly string[] | undefined'.ts(2322)
In addition to this error:
The expected type comes from property 'value' which is declared here on type 'DetailedHTMLProps<InputHTMLAttributes, HTMLInputElement>'
If I add an !
to the property, the error goes away:
<input name="userSub" type="hidden" value={user?.sub!} />
<input name="email" type="hidden" value={user?.email!} />
It also works if I add as string
:
<input name="userSub" type="hidden" value={user?.sub as string} />
<input name="email" type="hidden" value={user?.email as string} />
Why does this work and is it good practice to combine ?
and !
like this? Should I avoid using !
altogether? I've read that type assertion with as
is to be used with caution. I'm new in TS so greatly appreciate any explanations.
CodePudding user response:
These are both essentially different ways of handling values that are possibly null
or undefined
.
The main difference being that, with ?
you are telling typescript that the value might be undefined
, and that in such a case, it should simply return an undefined
.
While with !
, you are telling typescript that you know for sure that the property is neither a null
nor an undefined
.
as string
basically does the same thing as !
in this case, where you are telling typescript that you know for sure the value is of type string
.
Note that this is potentially dangerous, since if the value does end up being null
or undefined
, it could result in unwanted behavior.
As you can infer, this is a way to "silence" typescript, and therefor should only be used if you are sure that it is correct for your use-case.
Edit:
Here's additional information regarding ?
- aka JavaScript's "optional-chaining operator".
And additional information regarding !
- aka TypeScript's "non-null assertion operator".