Resolving the Block-scoped Variable Error in TypeScript
TypeScript is telling us we can't redeclare the name
variable because it has already been declared inside of lib.dom.d.ts
.
The index.ts
file is being detected as a global script rather than a module. This is because, by default, TypeScript assumes that a file without any imports and exports i
Transcript
00:00 Okay, what's happening here? Well, this is a pretty complex thing to explain. What's going on here is that we have a name variable and we're saying cannot redeclare block scoped variable name. So if we think about this,
00:16 this file here is basically being detected by TypeScript as not a module, it's a file inside the global scope. What TypeScript does by default is if you don't have any imports and exports inside a file, it will assume that this file is supposed to be a global script.
00:34 This is TypeScript's default because TypeScript is old. It's old, it's like 11 years old, right? And it's initially when it was built, it was meant to just compile JavaScript down into things that could be put in script tags in the browser that were meant to be in the global scope. And name, actually, if we go name like this,
00:53 you can see that it's actually like, it's something available in the global scope. You can command click on it and it's actually in the DOM here. So it's in the DOM typings that come with your project here. And so, because we don't have any imports and exports inside this file, then we are basically conflicting
01:13 with something that's already in the global scope. If we were to use constant name like this, uppercase name, then it wouldn't conflict. So let's say that we're inside a project that actually uses modules and this is a module, how do we tell TypeScript that this is a module? Well, we can add an empty export to the file.
01:31 And now, because TypeScript understands that this is a module, it's not going to throw that error. So that's great. So we can either do it with an export or with an import. So we can say import, yeah, assert or whatever, import anything. And now TypeScript won't throw this error.
01:48 But how do we actually tell TypeScript that every single file in our application is a module, regardless of what it thinks? Because you can kind of think of this like behavior is pretty legacy, right? The way it detects whether something is a module. Surely it should just assume that everything is a module.
02:07 Well, we can get it to do that. We can say inside our tsconfig.json, we can use module detection force here. So by default, it's auto. So this basically checks whether you have an import or export. If you don't have import or export, it assumes a global script and then changes it to,
02:26 oh, sorry, we don't want auto, we want force. This will force it to assume that every single file, whether it contains an import or export or not, is a module. And I recommend you turn this tsconfig option on in all of your projects that use modules. It is a relatively recent one, but my God, it's so useful
02:45 because if you have some beginners on your project, it's just going to throw you off because this is not going to cause an error at runtime, but if I go back to the problem set up here, it's not going to cause an error at runtime because this is a module, but TypeScript thinks that it's a script.
03:02 And so this is a really, really useful tsconfig option that I have in my default tsconfig setup for all of my projects. I can't think of the last time I actually used it. Oh no, I can think of a few years ago, I did like a project that was literally just script tags
03:19 in the browser, but yeah, modules are pretty awesome because they just let you segment your code and make everything easier. So module detection force is in my tsconfig cheat sheet, which I will also link to below. And it's a pretty nice setup for avoiding this error completely.