Enterprise TypeScript

Renaming Files to TS

Enterprise TypeScript

Check out a free preview of the full Enterprise TypeScript course

The "Renaming Files to TS" Lesson is part of the full, Enterprise TypeScript course featured in this preview video. Here's what you'd learn in this lesson:

Mike renames JavaScript files to TypeScript files in a chat project. Before fixing and type issues, a git commit is made to recognize the renaming in the git history. Now that all files in the project are TypeScript files, JSDoc comments are ignored, and type information needs to be provided with TypeScript.


Transcript from the "Renaming Files to TS" Lesson

>> The next thing we're gonna do with our chat project is rename all of the JavaScript files to TypeScript files. A couple type errors are gonna pop up, this is sort of the next wave of things we need to fix. We'll address those, we'll make a commit, and then we'll move on.

So I'm gonna close all my tabs here. The reason being, the JS files are going to disappear. When you have tabs open with JS files and you rename them with script like we're gonna run, it's easy to accidentally hit Save, and then you've sort of got the JavaScript and TypeScript, it's not great.

So rather than ask you how to do the renaming by hand, you can just run node scripts/rename-to-ts.mjs, and Enter. Cool, this has renamed everything. Well, a lot of things. Actually, it hasn't even picked up on all the changes yet. No, it has, good. I missed the little r here for, [LAUGH] renamed.

So we've got everything in our data folder, we've got all of our React components, they're TSX files now. Here's our utils folder, which is sort of low level utilities. Look, even our tests have been renamed, as well as the snapshots. And here's some more tests here. So I wanna make a Git commit right now.

And the reason is, if we were to go and start changing these files, there's a point where Git starts to think that this is like the removal of the old file and an addition of a totally new TS file. And I think there's value in preserving Git history so that you can track history all the way back to when it was written in JavaScript.

This is another big important thing for large-scale projects, right? You don't wanna make this change, and then bugs start popping up. And maybe you wanna run like Git bisect to try to track when the bug was introduced, but your Git history is sort of disjointed, it's worth it to preserve history.

Cool, and see all these nice little rename things here? That's what you want. We're gonna make a commit, and now we can do changes. But now, forever, Git will understand that this was a shift over. There's one more change that we need to make, we could have made it before we made the commit.

And that's that we have to change the entry point. In the case of Parcel that I'm using here to build this project, index.html is my entry point. And this is what we're gonna need to change right here. That's a JS file. There's a TS file. And this should work.

I have it a little different in the course notes where I have type=text/javascript, but this should be fine, just to leave it like this. And now that we've made that change, just for fun, I'm gonna amend it to my previous commit. Cuz it kinda belongs there. Part of the JS to TS rename.

Let's run yarn type check and yarn test. Type check and test. It's gonna run our Jesttests that are in this repo for us, they were already there. Okay, we got a couple of things popping up. So let's investigate these one by one. And again, I'm scanning through here and I wanna find the lowest level pieces of code that I can start with first.

I see a couple of things in the utils folder and the data folder. In this project specifically, you all would know best in your respective projects, but we all have a sense for what are like the low level, format a date into a string kind of functions. And then React components are sort of higher level where they're grabbing node modules, they're grabbing those date formatting things, and they're putting them all together.

So, let's start here. So we have one error here, const d=new Deferred(). Says it expected 1 argument but got 0. And it looks like we've had a constructor argument here for deferred that we haven't provided. So let's take a look at deferred. Well, it turns out we're not even using this description, we're not using it anywhere.

But I'm gonna follow the practice that I would advise you all follow, which is it's tempting to remove this, but we're trying to perturb this project as little as possible. And so what we can do here is just say, let's make it optional, even though it's unused. Let's pretend it might not be, but let's make it optional.

We're really trying to avoid changing the resultant code that spits out, the JavaScript code that comes out of this process. Anytime you do that, you run the risk of introducing a bug. And it's not that we shouldn't fix this, but it should be fixed separately from this conversion step.

Something like that. Now, you may notice, let's see, look at that, see description: any. What we're seeing here is that, since we've converted this to TypeScript now, this type information from JSDoc is ignored. And it may seem like it would be useful to, like still pay attention to it here, but imagine a world where we have something like this.

How do we reconcile that like, which type information should TypeScript pay attention to? Sometimes the docs are built based on this, right? So really, it's just saying, look, you can define types right in the code now, that's where you should be doing it. So you'll see a couple occurrences here where we're gonna have to just bring this into our code.

And by the way, this type checked as a JavaScript file before because this was optional with the square brackets here. It just failed to type check once we said it's a mandatory argument you got to provide. Does everyone understand why? Do you understand the difference between it being this, and it being optional?

We could have done this. We're just obligated to explicitly provide something. Undefined could be something we provide, right? But I don't wanna change that invocation of deferred either, I want this to become a string, an optional string. And we can get rid of this just to avoid confusion.

Wow, my hotkey. I'm putting my fingers all over the place here. Okay, sorry, we'll keep the word description here, that's better. Okay, this file looks good now, let's look at our api.ts, that looks good. I don't see any red errors on the header here. Let's look at error.ts, seems good.

Networking, seems good. All right, let's run our type check again just to see how we're doing. Okay, so we're good on the utils folder, now, let's look at data. So here, what's this happening here? API call, an argument for init was not provided. Hey, it's another thing that TypeScript no longer understands is optional, that's my bet.

Let's go and look. Let's click into API call. Sure enough, this has square brackets. So I'm just gonna bring this type in to the code, kinda like that. And then the string, put it for path. Let's see, I'm gonna type check one more time. If we get lucky, we might fix a lot of things.

Three errors in two files. Okay, again, starting with the principle of lower level file first, let's look at channel. All right, loading. It is the same error we were seeing before, we solved it with JSDoc, JSDoc types are ignored now. We're just gonna have to bring this into TypeScript world.

Something like that. Get rid of the comment, run it one more time. There are my tests running. The fact that I'm seeing my test run means that the type checking passed, right, cuz that's this is the command. Yarn type check has to pass for the test to run.

And they ran, and of course, there is a test for deferred, right? So here you can see we've got a version that passes a string. There's probably one, it always passed a string in. And so it seems like our tests really wanted to pass this string. We didn't have to touch our tests.

As far as we can tell, most of what we did was bring JSDoc types into TypeScript code. One of the things we lost as we started to ignore JSDoc is optionality of properties. And so, I would say this was a nice disciplined conversion step where we didn't, it's very low risk that we perturbed code more than we should have.

This is where I would make a Git commit. We've completed step two. We've renamed our files to TS and made the necessary adjustments.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now