Production-Grade TypeScript

Production-Grade TypeScript Converting to TypeScript Q&A

Learning Paths:
Check out a free preview of the full Production-Grade TypeScript course:
The "Converting to TypeScript Q&A" Lesson is part of the full, Production-Grade TypeScript course featured in this preview video. Here's what you'd learn in this lesson:

Mike answers questions about handling large type definition files, moving configuration files into subdirectories, maintaining type guard files, and how to handle publishing new versions of a library when there are still local type overrides.

Get Unlimited Access Now

Transcript from the "Converting to TypeScript Q&A" Lesson

>> You said that you use capital I in front of our interfaces name. I remember that the TypeScript team decided to walk away from this.
>> Yep, so they decided to do that for their own codebase. Personally, I find value in having more explicit visibility into the various things that I'm using.

[00:00:27] Like the minute that the VS code team allows this kind of thing to be highlighted differently, like visibly an interface on the screen, then I don't need my capital I anymore. But I do see a lot of value in being able to differentiate between a class, and an interface, and a type alias, all of which could be used interchangeably.

[00:00:50] But in one case, I'm crossing a lazy loading boundary, if I bring a class in, and if I import that. And in another I'm not I just see enough value in being able to spot that in my code that I personally continue this pattern. Although this is like semi-colons, they're not semi-colons, maybe not that trivial.

[00:01:13] But there are many valid opinions on this topic I'm just here to say that this is mine.
>> What if I add tons of types, I get some giant file, is that's the approach?
>> So the question we got in the class was, what if we have lots and lots of types?

[00:01:32] Do we just have one big type.ts file, and did we let this get to be 5,000, 6,000 lines long and if not, how do we organize things? The important takeaway here is, you should have four commonly used types. One or more files which could be organized into folders, however, it makes the most sense to you.

[00:01:55] But those files are dedicated to strictly type information. And the reason that you wanna keep things that way is there is zero asset size ramification or close to zero, right? For importing this type information, as soon as you add other stuff to these files, like if I were to move the guards here, like is I team.

[00:02:24] If that lived in types.ts, well, somebody that just needed IMessage, they're they're now paying the price of having several of these functions bundled together just cuz they needed to refer to a particular type. I mean, potentially, a lot of these bundling tools are not so sophisticated that they can shake away portions of modules that are unused it's generally like an entire module is included or it's not.

[00:02:52] And when you have modules that are exclusively designated as places for type information, you can feel very comfortable reaching in there, grabbing this interface out. And at worst, you get the cost of an empty module, included with your bundle, which will just sort of be a module with no exports at runtime.

[00:03:14] And that can even be stripped away if you bother to configure your tooling to do so, does that make sense? So the thing to optimize for is keeping almost zero overhead of nearly everything referencing these types.ts file and other files like it, right? No asset has ramifications and the way to do that, there should be no values in these modules, only types.

[00:03:44] A question from the class was, we have all these config files, right? We've got eslint, I even have .postcss and .prettierrc, and babel.config, all this in the root directory. Can we make a folder and start hiding some of this stuff away, the answer is some of it can be hidden away, a lot of it can't.

[00:04:07] And the reason is, editors look to discover these kinds of files in particular places. And the the benefit you get from sort of hiding them away like that is not extremely high compared to the work required to sort of teach these tools where to look other than the default location for their configs.

[00:04:30] And I'll tell you, even if you bothered to go and straighten that out, you would put yourself in a very small subset of users of these tools. Where these are options and setups that are just way more likely to break, than the simple mainstream use case and so you're exposing yourself to more risk.

[00:04:52] Here's what I would do instead, I would create a workspace VS code config and I would say you wanna ignore files See? So let me see if I can make this work. I'm actually pretty sure we do this at least in my VS code course, I'm not sure if Burke does it in his, well, more up to date one.

[00:05:32] But there's a way that you can tell VS code in your settings here to just don't show you the babel.rc, don't show you this, don't show you that. Or you could even map them into another folder in your workspace to just sort of get them out of the way.

[00:05:46] You have the TLDR here is, I would never want to move these away from their default location, I think it's more risk, more trouble than it's worth. And if you're working on a big project like a TypeScript project, you're charging money for, that has a lot of people working on it.

[00:06:06] You're gonna have a lot of this stuff anyway, there's just no running from that problem. So the question was, how do we make sure that our as our interfaces evolve, the guards evolve to match them? Which is a good question to ask because I pointed out that this is a high-risk part of your codebase.

[00:06:27] If you bake lies into your type information, TypeScript will believe your lies, and you will suffer because of that. So I'm gonna answer that in a moment, actually in the next section, it's a great segue with tests for types. So the way we're gonna solve that is with a test suite for this type information that we just made.

[00:06:53] So all I'm gonna do here is export them and then we'll carry this forward. So the question is, if I encounter a problem with types of my dependencies, I have fixes in my local types folder and then I published my library. Won't that be a problem for consumers of my library and the answer is, absolutely yes, it will be.

[00:07:18] However, this would allow you to keep working on master, to keep merging pull requests, to keep moving forward without cutting a release, right? And generally this is just to get you unblocked, you definitely wanna pay attention to this. And you wanna make sure that you're not inflicting pain on your customers.

[00:07:38] Cuz as I said before, this types.ts, this is included, this would be included with your library, right, it's a module just like any other. This stuff here you can think of this this little place for local overrides, this is just hacks and adjustments needed in order to make your library compile.

[00:08:00] So actually, let me walk back my answer slightly cuz I said absolutely it'll break off your users. It will absolutely break your users if the types that are exported, your public facing API surface include stuff that relies on those overrides in order to work. Then you'll have a problem, but if it's something that's just sort of the private implementation details like you need to use this new feature on service worker, an t's not something that's typed yet.

[00:08:32] But as long as it's hidden and it doesn't come out in your declaration files, no one's gonna feel that pain. You do need to pay attention to it, sometimes you can get away with it. And the way I would try to make it work I only have bad hacks to offer you in this space.

[00:08:51] I would say, see if you can get your fixes merged for real and then remove your hacks, make sure everything works, then cut a release. And if it's breaking for you, it's probably breaking for a lot of other people. Usually a lot of motivation to get this stuff fixed, but the problems are extremely tricky to solve sometimes.