Video 6M9aZzm-kEc
AI Summary
The video explains why 'as const' is the most underrated TypeScript feature. It demonstrates how 'as const' makes objects deeply read-only and enables precise type inference, allowing developers to derive union types from object values without repetition.
The speaker identifies 'as const' as the most underrated TypeScript feature due to its utility in many situations.
Without 'as const', object properties like 'roots.home' are inferred as 'string', not the literal value, causing type mismatches.
Adding 'as const' makes the object deeply read-only and infers literal types (e.g., '/home' instead of 'string').
Object.freeze only works shallowly, while 'as const' works deeply on the entire object.
'typeof roots' extracts the type of the const object, enabling dynamic value extraction without repetition.
By indexing 'typeof roots' with 'keyof typeof roots', you can create a union of all object values, similar to Object.values at the type level.
'as const' is a powerful tool for creating precise, immutable types in TypeScript, reducing repetition and improving type safety.
Clickbait Check
100% Legit"The title perfectly matches the content; the video delivers exactly what it promises."
Tutorial Checklist
Study Flashcards (5)
What does 'as const' do to an object in TypeScript?
easy
Click to reveal answer
What does 'as const' do to an object in TypeScript?
It makes the object deeply read-only and infers literal types for its properties.
02:01
How does 'as const' differ from Object.freeze?
medium
Click to reveal answer
How does 'as const' differ from Object.freeze?
Object.freeze only works shallowly, while 'as const' works deeply on the entire object.
02:39
What is the type of 'roots.home' without 'as const'?
easy
Click to reveal answer
What is the type of 'roots.home' without 'as const'?
It is inferred as 'string', not the literal '/home'.
01:30
How do you extract the union of all values from a const object at the type level?
hard
Click to reveal answer
How do you extract the union of all values from a const object at the type level?
Use '(typeof obj)[keyof typeof obj]'.
03:51
What does 'keyof typeof obj' return?
medium
Click to reveal answer
What does 'keyof typeof obj' return?
A union of all keys of the object (e.g., 'home' | 'admin' | 'users').
04:47
🔥 Best Moments
Most Underrated Feature
The speaker boldly claims 'as const' is the most underrated TypeScript feature, setting the stage for the entire video.
00:00Object.freeze vs as const
The comparison highlights that Object.freeze only works shallowly, while 'as const' works deeply, a key distinction.
02:39Whole Tamale, Baby
The speaker's enthusiastic phrase 'the whole tamale, baby' adds humor and emphasis to the deep immutability of 'as const'.
03:14Full Transcript
Download .txt[00:00] So someone just asked in the chat, like, what is the most underrated TypeScript feature? And I think the most underrated feature is as const. As const is just so useful in so many different situations. First of all, let's just describe what as const is.
[00:13] So let's say you've got an object here. We've got const obj equals this. And let's say we've got, let's just make it sort of a set of roots or something. Now, when we look at these roots here, if we hover over them, if we try to access like roots.home here, roots.home,
[00:28] then this is going to be typed as string. And if we try to, let's say, const go to root and we say, okay, I want you to basically be able to pass in kind of like any of these roots,
[00:41] any of home or admin or users, how do we type this? Well, we'd have to say that root is going to be like this or this or users. And that's pretty grim
[00:53] because it's kind of like we've repeated ourselves, right? You should not ever be doing this where you have multiple sources of truth for the same type. And this works, you know, like everything's fine. Go to root, you know, we've got this,
[01:05] we've got admin users, all autocomplete and great. But what if we wanted to derive one from the other? If I try to do this, if I try to say, okay, root.admin like this, it's actually going to yell at me,
[01:17] even though root is one of these members here So why is it yelling at me Let have a look You can see here that it was expecting this admin or users but you passed string Why didn pass string I passed this thing here
[01:30] Well, TypeScript thinks that what you've got here in this object is a string, just a plain old string, admin string. It doesn't understand that this is forward slash admin. And the reason for this is that roots.admin, it could be changed. It could be made into like whatever, like this. There's
[01:48] nothing to say that that's not going to be changed. So TypeScript infers it as a string that can be changed. So how do we then change it to be something that can't be changed? How do we make it so that
[02:01] this object here is like consted forever? Well, we say as const. And now two things happen. So first of all, roots.admin now gets an error saying you cannot assign to admin because it's a read-only
[02:15] property. If we hover over roots here, it's no longer home string, admin string, user string. It's home this, admin this, users this. Pretty cool. And so if I delete this here, now roots.admin,
[02:27] we can see that it's being inferred as forward slash admin. If I remove the as const, it's now being inferred as string. So as const, what it does is it makes objects read only. You notice
[02:39] that something we could have done here is we could have used object.freeze. Object does the same thing and it actually works on the type level too except it works at runtime Object prevents it from being manipulated So if I say root equals this for instance
[02:57] then it's going to yell at me for the same reason. But object.freeze works in a different way because it doesn't let you, doesn't do it deeply. So if I have like a deep root here, then I can actually modify roots.deep.whatever equals something like this. So object.freeze only works on the top level,
[03:14] Whereas as const actually works on the whole tamale, baby. Oh yeah, I haven't talked about this yet. So we need to talk about our go to root function because our go to root function now, it's still got all of this repetitive information.
[03:27] Wouldn't it be great if one could infer from the other? Let's say type of roots is type of roots. Type of is super useful with as const because what this means is we can extract the type
[03:39] of this type here. So we've now got access to home admin and users right there, which is super nice. Now then, how do we extract the object values from there? Well,
[03:51] I'll give you a little trick that you can do. Let's say we've got a root and type of roots. We're going to index into this kind of with a dynamic property access. And we're going to say key of type of roots What What is going on there So we got this root now is now this admin or users I can actually just replace this with root root And now if I say go to root and I got this admin users
[04:20] I can now add a new one. So new user is going to be users new. And I can now, this now gets added without me needing to like repeat myself anyway. It's absolutely beautiful.
[04:32] But let's take a look at this syntax. What's happening here is we're basically doing like an object.values, but on the type level. We're indexing into these routes and we're saying, okay, let's say type root keys is key of type of routes.
[04:47] What do you think this type is gonna be? This type is gonna be home or admin or users or new user here, right? So it's going to be like a union type of all of these keys. And now I could index into this route by saying,
[05:01] if I just index into it and say home, then I'm gonna get this one here, right? Because I'm just saying home, index into it with home. I can pass a union here, so I can pass in admin there.
[05:13] And now I get home or admin into here. But what I could do is I could just pass in this union, which is also generated from here, into this little slot there. And that means I get to do like an object values on it
[05:27] because the root keys then get passed into the type of roots. In fact, let me just reduce this down even more. And then I end up with all of the values of that thing.