Do you notice how in TypeScript that when you initialize a variable to a boolean, string or number, that TypeScript infers the type to be exactly that? A boolean, string or number.
For example:
let a = 4
a = 5
a // is 5 since type is number not 4
💡 Keep in mind, if you use
const
it prefers the more specific type4
This is a huge feature of TypeScript! Type Inference is essential to writing easy to read, and maintainable TS codebases. It removes a lot of verbosity as well as reduces the amount of type code that has to be updated when a type upstream changes.
However there are some times, where this can cause weird errors. For example, I didn’t guess at first glance that the below code would cause a type error:
type User = {
kind: 'user'
name: string
};
function userName(user: User) {
return user.name;
}
const user = {
kind: 'user',
name: 'Jane',
};
Can you spot the error?
If you caught it, great! If not, here's the issue you'll see from TypeScript:
Argument of type '{ kind: string; name: string; }' is not assignable to parameter of type 'User'.
Types of property 'kind' are incompatible.
Type 'string' is not assignable to type '"user"'.
Essentially what's happening is kind
gets widened to type string
when creating the user
object, but the function expects kind
to be type 'user'
.
Solution
So what's the solution?
Use as const
:
const user = {
kind: 'user' as const,
name: 'Jane',
};
When we use as const
it tells TypeScript that we don't want the inference to prefer the wider type of string
but instead use the more narrow type 'user'
. And in this case, our error above goes away!
Like what you read? Want to support me?
A cup of coffee goes a long way 🙏
Why not buy me one? https://ko-fi.com/danjfletcher
Top comments (2)
You are better off using something like
or
because it better communicates code intent. If I saw the
User
type as it was in your blog post, I'd be very confused as to why I'm seeing a field that can only ever be'employee'
.Oh you caught a typo! Let me fix that. It should be
'employee'
or'user'
everywhere in these examples.The example I was pulling from, instead of the union though, is like:
Where
kind
is the discriminator, if that makes sense