Issue
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.
Solution
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".
Update:
Does that mean that combining ? and ! is redundant?
Not redundant per-se, and will definitely work, but also not the best practice IMO..
I mean, you could do user!.sub!
for example, but over-using these operators is usually a sign of structural issues.
Firstly, see if it makes sense to adjust the types, this isn't directly related to your problem, but I feel like having | null | undefined
is a little redundant.
Of-course, both technically mean different things but usually can be interchangeable for most typing purposes.
Secondly, and this one kind of depends on the structure of your component, but what I would usually do to avoid !
is handle it in a conditional statement before-hand.
Typescript is smart enough to make the connection if it has been asserted in the same scope, and this way it's more explicit, and it also let's you actually handle the exception.
Example:
function someComp() {
...stuff
let myVar: string | null;
if (myVar === null) {
throw new Error('oh no!');
}
return (
// TypeScript shouldn't complain here -
<input type="text" value={myVar} />
)
}
Answered By - tomleb3
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.