
Lesson Description
The "Setup TS Configs" Lesson is part of the full, TypeScript Monorepos: Architect Maintainable Codebases course featured in this preview video. Here's what you'd learn in this lesson:
Mike walks through setting up TypeScript configurations for type checking and building processes. Mike also highlights structuring TS configs consistently across the monorepo for efficient development and compilation processes.
Transcript from the "Setup TS Configs" Lesson
[00:00:00]
>> Mike North: Now let's get into the TS configs. So in this next step, we're going to set up the right or a working TS config setup so that Visual Studio code still understands when to give us the red squiggles or whatever editor you're using. Like, the language server needs to be able to engage with the project.
[00:00:20]
You need to make sure that you're building the right thing and you need to make sure you can type check the right thing. What I mean by the right thing here is like when you're type checking, you should type check your tests and your source code. But when you build, obviously you don't want all of your test files to be part of a production build.
[00:00:40]
There's no point. So we're going to have to create a couple TS configs in order for this to work. So the first thing that we're gonna do, and we'll come back to this models folder when we're wiring everything back up, we're going to go back to our UI package.
[00:00:57]
We have a bunch of different tsconfigs here. This was literally what starting this vite project auto generated for me. We've got a tsconfig JSON here. This is what a language server is typically going to look for. Yes, you can configure it, you can provide some settings and point it to a different thing, but if you just open up a project, there's a tsconfig in the root.
[00:01:25]
That's what your language server is gonna look at. Before we started the course, this is what was working here. So we're gonna take this and we're gonna drag it into the root of our project. We're going to move it to the root of our project. We're going to have to change a couple of things.
[00:01:43]
Well, first off, everything in source and tests, this is not like there are no top level source and tests folders now. But we can do this. We can say, all right, any subfolder of packages, look for source and tests, and we're going to be tracking those files. Then I'm going to go, we need a tsconfig for the UI here.
[00:02:13]
So I'm going to create a new file here and in this case this is going to be regarded as a, not a rename. We're changing these files substantially. So creating a new file here is fine. What we'll say is this file extends tsconfig JSON and if we click there, we get to our root level.
[00:02:40]
Tsconfig that's how we know we have the path, right? And then we'll say includes. Sorry, I'm going to close the package JSONs here just so we don't get confused. So on the left we've got the root one, and this is for our UI. So here I'm gonna kind of grab all this, paste it in here.
[00:03:10]
Now my job is I'm going to prune this down a little bit. We'll undo what we just did for packages, because relative to this file here, there is a source and a test subfolder. And then we've got all this stuff that's TailWind specific, post CSS specific, vite, svelte, ESlint.
[00:03:33]
We'll deal with linting in a later chapter, but for now, ESLINT config lives here, so it's in the UI folder. Great. So this is what we want. This was the starting point. These were the original contents of includes in this file. And over here we can get rid of this stuff.
[00:03:54]
So just a summary of where we ended up. This is looking for all ts, js and svelte files in the source and tests folders of any of our packages. Then over here we have a complete set of within this package. What does this look like? Now, one benefit we have here is there are no strictness settings in this file anymore.
[00:04:24]
What we want to start doing is working towards a place where across our whole monorepo we can just point to this file and say, look, no implicit any. That's a rule I want to enforce everywhere in all packages. You don't wanna be going around and poking at individual TS configs eventually, right?
[00:04:44]
Like in reality, sometimes you're tightening things up and you want to do that on a package by package basis. But there is some benefit to having like a baseline layer of config, particularly around strictness. This is almost like linting settings. If typescript is a fancy linter, which it kind of is, yes.
[00:05:02]
>> Student: So aren't we including with the includes and the base tsconfig pointing down to the package directory, aren't we including stuff twice then?
>> Mike North: Yeah, let's get rid of this and see if it works. Bluntly, I forget whether we're replacing the includes array or whether it's appended to.
[00:05:27]
Let's delete that and let's see where we end up. We can always add it back later, but we are absolutely specifying it twice here. So we're going to see real quick, is this sufficient and all that you'd need to do in each monorepo packages. Whatever's extra, like, whatever's not in the source and test folder.
[00:05:47]
In this case, I want to type check all these config files in the root of the package. Good question. Okay, now we need to turn our attention back to models, so we'll close our UI folder here. We're going to need two files in here. Tsconfig JSON, tsconfig build JSON and the rule of thumb here is the tsconfig JSON.
[00:06:12]
This is the file that governs where you want your authoring feedback. Tsconfig.build.json is about compiling. Now, we want to make sure we're still leveraging a common set of strictness settings and module type and our target language level. But certainly the includes are going to be different here. One of these should point to your tests, and the other should only point to your source folder.
[00:06:40]
So in our new tsconfig.json, it's going to, again, extend from the base the root level tsconfig.json, and let's see if this is sufficient. Yep, that looks good. And tsconfig build this should only include source. In this case, don't worry about extensions. It's all typescript files. We don't want the tests to be compiled.
[00:07:30]
Let's try our build command again. Wait, sorry. Before I do that, we need a couple of things. Compiler options. All right, noEmit false, this is a double negative. What we're saying here is, yes, emit true. We're going to say the out directory is dist. Without this, you're going to end up with a js file and a distributed DTS file right next to your input typescript files.
[00:08:03]
And personally, it's kind of messy to me. Rootdir is source. Now, what this means is in our dist folder, we want to see the compiled results of our source folder. At the top level of the dist folder, we don't want to see disk dist, source, index, DTS and index js.
[00:08:30]
We just want to see dist index js. So this is sort of like the root of what is to be compiled. And this is a library. So let's make sure we build declarations. We have to opt into that and four options. That looks right to me. One more thing.
[00:08:51]
I want to do this. So why do I want to do this? Why not point to the base package JSON? Well, this still means that if I wanted to have some strictness settings here, if I wanted to say compiler options. No fall through cases in switch. This lets me have a convention where it's always the regular tsconfig JSON where per monorepo package strictness settings are set.
[00:09:21]
And so, you can think of it almost like you've got the base level tsconfig that threads up to each monorepo's sort of like authoring tsconfig and then the compile tsconfigs. It's going to look very much like this in every single library that you have. Because all this is doing is saying, okay, forget the test folder.
[00:09:46]
Also, we're actually compiling stuff and here's where to put the output. But these files are just commoditized. We're going to see when we create other monorepo packages, we're copying and pasting these things. It's a very uninteresting file. And if you were doing a large scale monorepo, this would be the kind of thing that you would template.
[00:10:05]
Like you'd use tspoet or something like that to just crank one of these out. And you know, it's not something that a human should really be messing with. All right, let's try to build. Ooh, sorry, outdoor, not out. Hey, there's something. What happened? The thing that I said that makes things messy happened.
[00:10:41]
Did I get confused here? Outdoor is dist. There is stuff in the dist folder. Let me blow this away and see what happens. I'll blow this way. Let me just check my build script here, make sure that's right. Build tsconfig, build JSON. Yep, and I'm in the models folder.
[00:11:28]
You know what, is probably the last time I ran the build command and maybe I just wasn't paying attention to my sidebar, but this is the expected output. Maybe those files I just deleted from when I attempted the build and there wasn't any. We hadn't put these compiler options here yet.
[00:11:51]
Anyway, this is what we're looking for. So we've got our index dts, right? We've got our index js, which is like the same things here. I mean really, this is just type information and so. Interesting. Were these classes. We have enums. That's why we're getting some compiled output.
[00:12:17]
Enums are not purely type information, they are values. If we look in. Yep, there you go, this is our string based being created. So great, so we've got some meaningful JavaScript. We've got some meaningful typescript. Let's try dev mode. We started compiling in watch mode. And so what that means is if we were to go here and say, I'm gonna add a new property, save, you can see, if you're watching closely, every time I save a file things update.
[00:12:59]
If I were to have any build errors we'd see those pretty clearly down here, right? Get a nice link we can click to go to the line. So great, so we've got a nice script for rapid development, we've got a script for building. One more thing we have to give attention to is exactly how is this package exporting what it has in its dist folder.
[00:13:20]
So go into your package JSON and we're going to add a couple new fields types and we'll say distindex d ts and module this is dist index js so think of these as the type and runnable code entry points for this library. So when another package imports this, we're saying where do you go?
[00:13:47]
Where is the build artifact?
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops