EPISODE 1757 [INTRO] [0:00:00] ANNOUNCER: TypeScript is a superset of JavaScript that adds static typing with optional type annotations. It was created at Microsoft and first released in 2012. TypeScript ESLint enables ESLint and Prettier to run on TypeScript code. Josh Goldberg is a host for Software Engineering Daily, the author of a Learning TypeScript by ?O'Reilly, and a Microsoft MVP. He's also a maintainer of TypeScript ESLint. In this episode, Josh speaks with Pawe? Borkowski about the history of TypeScript, why it was created, some of its current limitations, the TypeScript ESLint project, and more. Pawe? Borkowski is a tech lead and a software engineer with a background in launching products and startups and big companies. He's also the founder of Flat Social. Check out the show notes to follow Pawel on Twitter or LinkedIn, or visit his personal website, pawel.io. [EPISODE] [0:01:05] PB: Hi, Josh. Welcome to Software Engineering Daily. [0:01:06] JG: Hey, thanks for having me. [0:01:08] PB: So, let's start with the first question about your background a little bit more. How did you get into programming and what were your first steps in the world of building software? [0:01:17] JG: So, my dad was a computer science professor, which meant throughout high school, at least the first half, I didn't want to do anything involving computer science. But I was really into photoshop and graphic design, and I ended up wanting to make a website for myself, my little, we call them forum signatures, little photoshop images I made on the Internet. So, I got into HTML and I took a Java class in high school and kind of fell in love with it. So, I went to university for a for a four-year computer science programming degree and haven't looked back since. [0:01:43] PB: You had still some background from before, before you actually got to the university and tried coding before, so it wasn't your first experience? [0:01:50] JG: Yes. I miss the days of being able to spend time photoshopping my friends' faces onto animals, but I knew pretty quickly that coding was something that I really enjoyed and could make money off of. [0:02:00] PB: I still do the Photoshop part, but I don't advertise that in my LinkedIn. I love that. So, you are the author of a book called Learning TypeScript that has been published by the famous ?O'Reilly Media. So, I think you're the best person to ask in this room. What is TypeScript? [0:02:17] JG: Sure. TypeScript is a typed superset of JavaScript. What that means is it's like the JavaScript language. It has all the stuff you know and "love" about JavaScript, but it also adds in a few things that make it a little easier to write a lot of JavaScript. It adds in syntax like a formal specification-ish where you can describe what shapes things are going to be, like if this function takes in an options object with certain properties or string or whatnot, and it provides a type checker, which is the thing that looks at your JavaScript and/or TypeScript files with or without those nice types and type annotations. It lets you know if you might have messed something up. Like if you say this function takes in a string but you passed a number. I can, on the command line give you a report of that or in your editor, I can give you little red squiggly is explaining hey you messed up this is where you said it would be something else. So overall, it's a nice way to write what is essentially JavaScript but much better described with types and much better checked at development and build time. [0:03:11] PB: What's the story behind TypeScript? Because that's been created at Microsoft, right? At the moment I think it's a more of an open source and community around this and I was wondering who decides at this point, which direction TypeScript will evolve in, and what's the decision process in that? [0:03:26] JG: It's a good question. TypeScript is a Microsoft project. It always has been, and for the foreseeable future, will be. It was actually one of the first major open source projects to come out of Microsoft, even predates GitHub being the common code platform for everyone to use for these things. So, at the beginning, TypeScript was one of several languages that was trying to work in that space of, we're a really big company that's trying to build JavaScript applications like for example, office on the web, word.office.com. JavaScript itself is god awful at the time at least, and still to an extent today at say letting you write 1,000 files or 100,000 files. If you change one file, back in the day, it was very difficult to know which files would be impacted, what are the type signature changes, what factors or bugs would you have to work with? So, Microsoft made that because they were trying to compete with things like Google Docs and other big web apps, and they found that they were used to the really nice development experience of like Visual Studio, with C#, and .NET, and wanted that in JavaScript land. So, these days, it's still a Microsoft project. The TypeScript team runs it, but it's open source on GitHub. They're extremely active. I've contributed as an external contributor. I filed issues and pull requests. For the most part they try to stick to just the types space. They don't really try to compete with what's getting added to JavaScript like runtime features in JavaScript. But they do work pretty closely with TC39, the committee number 39. I don't know what the other 38 are that decides actual JavaScript to make sure that they're just working in the type space and not conflicting with JavaScript itself. [0:05:00] PB: I was wondering, for example, if you have TypeScript, then obviously JavaScript would be the dependency for TypeScript. So, if something changes within the JavaScript world, then the TypeScript will have to follow in order to keep it consistent at the same time. So, is it like a unidirectional decision process or is it them talking together? Because I think quite often we use those tools. [0:05:22] JG: Yes. Nothing at tech is ever very formalized exact process met. There are always wacky side conversations and whatnot So, I don't know exactly how intricate the TypeScript, JavaScript TC39 relationship is. But I will say is that the TypeScript team makes a very strong effort to not get in the way of JavaScript. JavaScript is one of the most difficult languages to work on in modern times because it's in this bizarre unique position where you can't break the web and you have to maintain backwards compatibility ad finem. You have to support IE9 for modern JavaScript features, or at least you have to support that you don't break Internet Explorer 9 running IE9 tailored websites. So, as difficult as it is to write JavaScript, it would be that much more difficult if TypeScript got in the way and started introducing runtime stuff and polluting the namespaces. So, for the most part, JavaScript adds runtime features and then TypeScript adds type system things. They very explicitly try to mostly innovate the type space. [0:06:20] PB: Do you think that TypeScript maybe would ever go more into a standalone part to separate itself from JavaScript or? [0:06:27] JG: I don't think so. There are some community projects that kind of take TypeScript and put in a new fun place. For example, assembly script is a really interesting one where instead of compiling your TypeScript code down to JavaScript, it compiles it to WebAssembly by code equivalent. The target of this is that you can write your nice TypeScript stuff, even use some TypeScript libraries, but then ship in WebAssembly. So, the assembly script language is really cool. But the main goal of TypeScript is not to replace JavaScript. It's not the old Microsoft embrace, extend, extinguish, if anyone remembers that horrible mantra from back in the day. It's that there is an existing JavaScript ecosystem. We're stuck with it. We love it. It's got its quirks. It's got its beauty. TypeScript is a way to make that ecosystem more pleasant to deal with, more pleasant to write code in. If you were to kind of separate TypeScript and JavaScript, you'd lose the beauty and then the power of the JavaScript ecosystem that would make TypeScript much less valuable as a language. [0:07:23] PB: If you could change or improve anything about TypeScript itself, what do you think is there to be still improved? [0:07:30] JG: There's always stuff to be done. The TypeScript issues on GitHub are numerous. I think there are over 5,000 of them. For me as someone who tries to teach people TypeScript and is focused on tooling around it to make it easier to use, the biggest gripe I think is that there are some language features that are a little misplaced in today's world. The biggest one is the fact that we have both types and interfaces. Those are two different ways in TypeScript to describe, "I have an object or some shape and I want to be able to later refer to that shape by some name." A lot of languages with types have interfaces, C#, Java, C++. All of them have that or structs or some equivalent. The fact that we have two of them in TypeScript and the community can never decide on which one to use, it's almost tabs versus spaces level of debate, it's kind of inconvenient. There's a reason why this is the case. They kind of evolved organically. Type Aliases is one of them, kind of didn't start off super, well, it wasn't originally in TypesSript and got added more and more to the point where they can do most of what interfaces can do. But if we could just reset, go back 10 years and recreate it again, we'd probably have a little more clear delineation or even merging of the two concepts. Something that's a little more thought out from the beginning. [0:08:42] PB: I was just wondering what was the actual, at the end of the day? Because I use sometimes interfaces. For example, I define props for React component and I'd usually use an interface for that. But like I never actually thought, "Hey, how about I'm going to use a type, because muscle memory just continue coding it up." [0:08:58] JG: Yes. So, you can use an interface. The way you do it, honestly, the way I do that's my preference for a shape. Interface fruit name string, value number, whatever. Or you could use a type alias. Type fruit equals object curly's name, string, value number. Most of the time, the two are equivalent. There are some edge cases where you have to use an interface or you have to use a type. Type Aliases can have unions, which are things saying this can be one of several possible types. This can be string or number, which is a feature. Not a lot of programming languages have in their type system. Then interfaces can merge together. If you have the global window interface and you say, "Hey, I added some global to the window. Now, all windows should have it." You can do that with interfaces. So, it really is muscle memory. In TypeScript ESLint, one of the projects I work on that helps standardize stylistic and conventions for TypeScript in the community. We just say, "Look, pick one and go with it." The most important thing is just being consistent with yourself. [0:09:53] PB: I think, a part from that, there were also the name conventions that stumbled upon a thing on GitHub was this discussion a while ago. Should you start the interfaces with I, for example. Like if I component and then you just call it by personally, this is also my muscle memory. So, whenever I leave an I in front of an interface, wherever in the code base, you kind of know that this is me. But then other people weren't using this, I was wondering, like, does it really make sense? Because for me, for example, it was easier to follow this convention instead of to kind of make it easier to read. But for myself, maybe not. [0:10:21] JG: There are very old code conventions that are kind of still in the community here. One of those is the idea of prefixing names with what those things are. I can never remember, there's this whole deep dive, also that folks I'm like - [0:10:34] PB: - Hungarian note. [0:10:36] JG: There it is, Hungarian. Yes, a lot of those notations started out of one or two possible concerns. One is that I want to be able to describe the type of this thing, but I'm working in a language where it's actually really inconvenient to find the type. Go to reference or go to definition, the way we have in TypeScript. So, you'd put like T something or I something to say, it's like a template or an interface. That is not super useful these days in TypeScript, because we have such great tooling, same with C #, Java, Kotlin, and Swift. So, for the most part, the recommendation is don't start your interfaces with I always. It's redundant. It's unnecessary. There are better ways of knowing what's an interface. But some people still do it. [0:11:15] PB: Yes, I still do. But I'll learn at work from other people. That kind of introduced me to TypeScript in the beginning, and I just kept on doing this. But occasionally, you don't question it, after a while, keep that convention. I was wondering, do you have any tips for TypeScript developers, people that use TypeScript, how to be most productive with the language? What things to avoid? What things maybe to focus on more? [0:11:35] JG: Yes. I'd say to start, if at all possible, treat it as something you should learn. I know not everyone has time for everything, and this is yet another random technical thing people are suggesting one could learn. But it's really useful to understand the tools you're using. So, read the TypeScript docs. Honestly, the release notes on new versions do a fantastic job of explaining new features in TypeScript and then link to the appropriate resources. If you know TypeScript well, it becomes a much more pleasant process to write it. That's my number one tip. My number two tip is, of course, use a linter, ESLint, or Biome, or TypeScript ESLint, whatever it is, something that can enforce good best practices and consistent styling. That'll help you get the most out of your language and catch a lot of bugs for you. [0:12:16] PB: I think this provides a nice segue into ESLint. It was in general linting, the process of linting, and ESLint. What it is? Why do we need it? Why, for example, I need this in JavaScript versus I might not need a I think in Swift or not any other strongly typed languages? [0:12:34] JG: There are three really common static analysis tools. Tools that run on your code, but don't actually build and then run your code. Static analysis, as opposed to dynamic, like testing. Formatting, linting, type checking. Formatters, like Prettier, are very dumb in a good way. They just reformat your code. That's conceptually the simplest. Although fun fact, a very difficult called implement. Linters and type checkers are two different things. Type checkers, like TypeScript, just look out correctness. They provide a set of APIs that other tools can use to learn about your code, about the types, and they'll tell you if you have a type mismatch, like an assignability issue. This is supposed to be Boolean you would assign, I don't know, string array, whatever. But they don't check for stylistic consistency. They don't check for likely bugs. They don't check for, "Hey, my team said that we should move from that deprecated function to this new function, but you're still calling the old deprecated one." There are a whole plethora of things you can do with linters that just are not a good fit. Just do not make sense in type checking. So, that's why I definitely recommend if you're using TypeScript, if it's justified at your scale or project to use TypeScript, it's almost certainly also justified to use something like ESLint to lint your code. [0:13:44] PB: You an open source developer, we could call wizard at TypeScript ESLint, which is very popular. I was wondering, what is your role in the development? How did you get into this position? How did you start with being the open source developer in this project? Why is it? Why is it separate, for example, from the ESLint itself? [0:14:04] JG: We get a lot of questions. When is ESLint going to build in TypeScript support for its class? It's a very interesting debate. So, ESLint is the standard JavaScript linter. Fun fact, it does not actually stand for ECMAScript Lint. Nowhere in the documentation does it specifically say that. So, we've been trying to find extra fun things to call it like extra spicy linter. But it's basically the ECMAScript linter. It's just for JavaScript/ECMAScript. That's all it does. It does a great job of that. It sets up a nice base that plugins another ecosystem community projects can build on, but it doesn't support random ad hoc extensions to JavaScript, such as TypeScript, or Flow, or CoffeeScript, or Enso or anything. That's a philosophical standpoint that the Technical Steering Committee of ESLint currently has, had for the last decade plus and will probably have for a while. So, then it comes to the community to build in, let's say you want a parser that takes in TypeScript syntax and converts it to a format ESLint can use, or if you want to have an ESLint plugin, which contains a whole set of rules specific to, let's say, TypeScript code. So, that parser and the ESLint plugin are the main things that TypeScript ESLint provides. So, you're using ESLint, and then you add on TypeScript ESLint to additionally be able to support TypeScript, the same way you might add on some other community plugin to support like JSON Linting or Markdown or YAML. [0:15:21] PB: I was just wondering what really, because you say that in this case, what I understand that the TypeScript ESLint is more of a plug-in to ESLint, right? So, you can add it on top of it. It's not like a standalone for anything. How much overlap you have in terms of, because, and maybe speak a little bit about the linting rules, because a linter operator, there will be a list of linting rules. For example, don't do this, don't do that, remove this part and so on. So, I was wondering, who decides what those rules are, and how do those new rules come into play, and how do they become outdated? [0:15:50] JG: Oh, yes. There are two kind of tiers of rules other than deprecated or old, we don't like this anymore rules, that a linter or a linter plugin might have. The base level is, these are the rules provided. We're not saying how you should use them, we might give you default options, but they're just available. Both ESLint, which has its own team, I'm on one of the ESLint teams, the Committer team, and then also TypeScript ESLint, I'm one of the three maintainers, along with our committers. We each provide a bunch of rules. Then also, ESLint and TypeScript ESLint provide what's called a shareable config or preset config, which says within those rules, these are the ones we recommend under a name like, let's say recommended or for TypeScript ESLint, strict or stylistic. All of those shared configs, the ones that we actually recommend people use, those were informed by years and years of people trying out linters, finding which rules they like or don't like, screaming at us on the Internet, us or them back in the day of, "Hey, we really hate that you put this in recommended. Stop doing that. That doesn't work for us." Or, "Hey, this should be in recommended." So, in theory, or ostensibly the project itself, like the ESLint project determines what's in recommended or TypeScript ESLint determines what's in its recommended or stylistic rule sets. But really, both projects try to keep that very open with the community. It's an open dialogue. If you want to change something, you can file a GitHub issue or discussion or post on Discord. So, they're supposed to, and I think for the most part, really do, reflect what's actually currently community accepted best practice for JavaScript in ESLint or JavaScript plus TypeScript in TypeScript ESLint. If I'm wrong about that, if there's a rule someone doesn't like, please yell at us on the Internet so we can make it better for you. [0:17:29] PB: So, the rules, as I understand, they just came through years and years of the flame of Internet arguments. [0:17:35] JG: Yes. Through that crucible was forged, the TypeScript ESLint - [0:17:38] PB: The TypeScript ESLint emerged. So, at the end of the day, there'll be like one of three of you deciding is this going in or not, as maintainers? If somebody has a suggestion or there's a big discussion? [0:17:48] JG: We go by consensus. There are three maintainers, three or four committer team members. If one of us really hates something and everyone else loves it. We'll still try to hash it out, figure out. Part of being an open source contributor or maintainer or committer is being able to work with people who you have very little actual shared context with. I don't think I've met any of the other TypeScript ESLint or ESLint committers or maintainers in real life. So, we just talk about it on the Internet and try to solicit input when possible. I really want to emphasize that it is a consensus driven process. It's not one person said and then thus it shall be said. [0:18:21] PB: Yes, I was just wondering, because also specifically within the world of JavaScript, I always compare JavaScript in all the frameworks around like this zoo that you go in and there is like a lot of animals, and each one is of different shape, and every person that works in the zoo does things in a different way because you can move it within, as a JavaScript developer, from project to project. I spent a lot of time in the beginning of a project picking up new frameworks, learning, for example, if you switch from angular to react, the concepts will be different. We went through so many state management libraries from MobX to Redux and so on. As soon as you switch, the project is almost like a stressful moment because those new animals jumping at you. So, you're just wondering the person who decides, apart from obviously this, then this metaphor, who will decide like, "Okay, this is the way we're going to write TypeScript if you're using the TypeScript ESLint." I was looking if there's a - [0:19:11] JG: Yesh, in the projects themselves, like the core projects like ESLint for TypeScript, we try to just focus on things that are universal to everyone. We wouldn't encode, I don't know, like Angular or React specific stuff. I personally have a very soft, sweet, happy spot in my heart for MobX. Love that library. I miss the days of working with it. I love MobX. I love that you brought it up. Great library. [0:19:34] PB: I work with them right now. [0:19:35] JG: Shout-out MobX. [0:19:38] PB: I'm actually using MobX state - [0:19:38] JG: I love it. What a great library. [0:19:40] PB: It is great. But in the beginning it was pain, but then like the first week I think, because when I was learning a good jump on this project, I was like, you have to do it in a week with a new library that you never used in your life. So, like you had to learn really fast. But then once I've seen how people used it in the wild, they organized the code really nicely. I recommend this now for any new project that I take on. [0:20:01] JG: That's great. If only there was some tool that could automatically run in your editor and give you best practices and other conventional feedback as you learn a new tool. That's one of the downsides and the positives of ESLint that every project typically has, like every popular mainstream JavaScript project typically has an ESLint plugin. There's an ESLint plugin for Next.js. There are actually two for React, one from the React team and one from the community around more stuff. There's also a general JSX plugin, bajillion plugins, plugins everywhere. So, on the right side, if you use something new and popular, like if you switch from, I don't know, React to SolidJS, there will be an ESLint plugin you can use. That'll help you with that. That plugin will have been informed, for hopefully, and I think generally, by the community, by people collaborating the same way as we do on instead of the general typescript stuff, the specific, whatever, React or SolidJS stuff. Or it'll be from the team itself and they tend to know best how to do the thing they built. The downside then is, yes, you have to configure some new plugin and some of them aren't just put one line in and it works. Some of them have a little configuration. So, that's one of the bigger ecosystem pains we have in ESLint. Just getting that dang config file to work with your specific, unique, glorious JavaScript situation. [0:21:10] PB: For me, usually, as soon as I set it, I just want to forget it. I want this to work and focus on the project, right? It's safe just to keep the ESLint from saving me or any other developers from pushing something that would be obviously wrong and just keep it within the CI/CD pipeline and kind of block the commits that, for example, would be not adhering to the rules that we have selected or have been selected for us at the same time. [0:21:34] JG: As much as I love dev tooling and putting hours upon hours of work, a week, or even day into this stuff, we should recognize that most developers don't want to care about this. They really don't want to care about semantically, should this rule be in the strict recommended preset? They just, as you said, just put the config there and let me be productive. One of our biggest tasks as open source maintainers is to try to let people be productive with as little work as possible on their ends to work with us. [0:21:59] PB: So, recently you have released a new version of TypeScript ESLint. It's the version eight. You're in the process of releasing currently. So, I was wondering what's the current stage of it and what are the biggest changes and improvements that you are putting in? [0:22:12] JG: Oh yes. there are two big headliner features for this release specifically. One is that we finally support ESLint v9. I have found it to be a pain point in the community both that we don't have the same version numbers ESLint, we're one behind. And also, that the latest ESLint version v9 came out beginning of 2024 is not actually technically supported by TypeScript ESLint v7, our previous current major. So, there are some breaking changes, some internal shenanigans we had to do, but TypeScript ESLint v8 actually supports ESLint v9. Boom, hooray. No more peer dependency warnings. The second thing is that we have a new way to do what's called type to linting. It's one of the big value props of TypeScript ESLint, that in addition to supporting TypeScript syntax and giving you rules around that syntax, we also can actually use the TypeScript type checker, the APIs from TypeScript's type checker, to make a significantly more powerful class of lint rules. All type lint rules. The upside of that is, oh, my gosh, they're so freaking powerful. We can detect bugs from asynchronous code execution by detecting what's a promise, did you make a promise, did you handle it correctly? Something no other linter can do with JavaScript land reliably. But then the downside is it's actually kind of a pain, again, to configure it because you're merging together two tools, ESLint and TypeScript that aren't architected with the same goals. So, we have this new thing called the project service in TypeScript v8 that is faster than the old ways of doing things should ideally, and in my experience, generally does make a much more straightforward, streamlined configuration experience and works more similarly to how TypeScript works in editors like VS Code. So, you're having generally more reliability in your type linting, fewer weird discrepancies between typescript and ESLint. [0:23:52] PB: So, how does the project service work? Can you speak a little bit more about it? [0:23:56] JG: Sure. There are two ways of setting up type linting and TypeScript ESLint. The old way is called project, parser options not project. The new way is project service. In the old way, we would use manual TypeScript APIs where we would be told by you which TypeScript projects or TS config files, your TypeScript configuration files to use. We can auto detect them, the closest for each file, with project true, or like taking a string array. When you start linting, we create what's called a TypeScript program, which is like the representation of your TypeScript going on programmatically for each project. And then whenever you want to lint a file, we'll ask TypeScript APIs, "Hey, given this file path in the corresponding TypeScript program, give me the type information for that file." The problem with using manual TypeScript APIs is we mess it up sometimes. People give us the wrong projects or there are like weird TypeScript features that aren't quite supported in our tooling yet, like project references is the name of a feature our old project tooling didn't support. So, what we do now instead with Project Service, but you don't have to use one of the other. You can use one of the other up, to you, but we recommend Project Service now is we call a much more, I think the term is black box, like just use whatever seems right to you TypeScript API, actually the same one that editors like VS Code use. So, what we'll say is, "Hey, this is the default settings for TypeScript, if you need them. This is the project service thing. Go find me the type information for this file." Because we are calling to the same APIs as an editor, you use the same logic as an editor to determine the settings for each file, so we support project references out of the box, and it's a lot more optimized because this is what VS Code uses and other editors. This needs to be fast. We've seen performance improvements of 10% to 20% out of the box. We've seen people go from like 20 lines of config up to, in their ESLint config down to 1 to 10, 1 to 5 most commonly. It's been a win around the box. The random edge case bugs that are why we've waited until v8 to make this thing marked as stable and usable, but we're really excited about it. I think it makes things a lot nicer for folks. [0:25:56] PB: Especially from the performance perspective for large projects that are already there, they need - if you have this in say, within Visual Studio Code and you change one thing, and then ESLint starts, for example, updating, it might take a while. [0:26:08] JG: Oh, my gosh. [0:26:09] PB: So, occasionally, I even had to switch top for a while in larger projects just to run faster and then do it right do it right after. So, I was wondering when you said that you're getting the type information from a file. Imagine that I have a, for example, Next.js route with some handler or some frontend file. What do you mean that you get the types from the file? Do you extract basically all the entities and the types that were there, all the interfaces, or all of the types that were imported? [0:26:34] JG: I love this question. Let's talk about how TypeScript works, about how static analysis works. People get scared when you say phrasing like that, but it's actually, I think, very surface level. We're not going to dive too deep. The way tools like ESLint and TypeScript represent or reason about your code is with what's called an abstract syntax tree, or AST. It's a big object that describes all this stuff in your file. It's called a tree because you have things with children. You might have a variable statement where the children are the name and then the initial value, and then also the kind if it's cause var or let or whatnot. The way ESLint rules work, each thing you might want to enforce with ESLint is enforced by one rule, is the rule takes in your AST, the big object describing your file, and it looks for little patterns in the file. If you have a variable declaration where the kind is var, hey, you should use let rule will kick in and say, "Ah, you should use let." TypeScript also represents things with an AST. It's a different format than ESLint, but it's the same idea. So, when you have an ESLint rule that runs through the TypeScript ESLint tooling, what you can do is you can ask our APIs to ask TypeScript APIs, given this node, this thing in the AST, what does TypeScript think the type is? If you give it the name of a variable and that variable is initialized to a string, TypeScript will tell you, "Oh, we've inferred it to be TypeString." Thus, your ESLint rules can use that type information alongside their normal AST checking logic. Does that answer what you were looking for? [0:27:59] PB: Yes. So, then you extract all of them and then when you would apply the ESLint rules on that, on top of it, right? For example, you would have the AST tree of the file itself. You would ask TypeScript, for example, what the types are with the ESLint, because I never looked through the ESLint rules at the code. So, I'm just wondering what did they actually do? They run through the entire tree and just try to analyzed because you said that some of them might be checking if it's a var and it should be a let. So, this seems like a more simple one that you have arrived at a certain node where you figure out okay, the var should be let, that's it. But given that this is a tree, I think that some of them might be getting much more complicated than this. Is that correct? [0:28:37] JG: Oh, yes. Most of them honestly are relatively straightforward, but some of them are just ridiculous. Some of them I shudder to work on. We've built up a set of utilities, ESLint has, we haven't typed ESLint, that make it easier to work with this stuff. For example, let's talk about unused variable detection. TypeScript actually has a couple of compiler options. No unused locals, no unused parameters, that can have TypeScript error on something being unused. That's like the most linter area thing TypeScript does. They've talked about adding more, but decided no, let's let the linters do that because people actually really want to configure this stuff. If you want your lint rule, no one used vars to detect this stuff. Well, each lint rule works on one file at a time. It takes one file's AST with some metadata about the file, and is supposed to call some function whenever it sees a complaint. How do you know if a variable is unused? Well, what if the variable's name is known? Let name equals josh. You can check for any identifier. It's called a name. And if there's only one identifier in the variable declaration, then you know it's unused. But what if you have a bunch of variables named name or whatever equivalent in a bunch of different functions? How do you know that function log Josh has a let name and log Powell has a name and those two names are different? So, then you have to do what's called scope analysis, which is where you build up a big description of for each variable, for each identifier, here's where it was declared. Then you get the concept of scoped identifiers, and then you can check, is this scoped identifier used anywhere else? So, that's not even using type information. That's just one of the more complex lint rules that one might want to run on code. [0:30:11] PB: Would that also work, for example, if you are exporting a variable, right? So, we can say it's unused within the file, but then you're exporting it to another file. It wouldn't pass this check or it would? [0:30:20] JG: It would pass the check because in export, hey, that's using the thing, which actually is one of the really key structural limitations of ESLint and kind of a TypeScript that they both generally work on a per file or per, whether this is used at all basis. If you export a variable that's never used anywhere else, ESLint has no way of checking for this. We've tried to build this rule in ESLint, but structurally, it's just hard because Lint rules are designed to work in one file at a time. So, I actually recommend people to go use another tool for that, something called Knip, K-N-I-P. It's a Dutch word cut that does this kind of cross file analysis for unused coder dependencies. Great tool. Highly recommend. [0:30:59] PB: That makes sense, because it's much easier from the perspective of ESLint to find an unused import than to find an unused export, right? Because the import, you can see, okay, you import this and you're just not using this within the file. [0:31:09] JG: Exactly. [0:31:11] PB: That's interesting. It's still like if you have like large code base and a lot of those tasks I would imagine are recursive or just running through the tree, there in the back trying to check obviously with a lot of optimizations, and there is no wonder why occasionally that this will get slow. [0:31:24] JG: Yes. We've found is that in addition to complex config files performance of type-checked linting of a cross-file linting is one of the big, top three pains in the ESLint ecosystem. That's why there are alternative linters like Biome, oxlint, lint that are getting popular because although they don't have type linting yet, they are shockingly fast, or there's a magnitude faster and people love that. So, we're working on performance in TypeScript ESLint. ESLint is going through an early stage of a rewrite which we'll hopefully structurally help with that too. But fundamentally, yes, if you're linting with a lot of files at once and or with slow stuff like full TypeScript type checking, performance is one of the tradeoffs you have to work with. [0:32:09] PB: Yes, because you're not only, as you mentioned earlier, but to reiterate on that, you're not only on the TypeScript ESLint team, you're also on the ESLint team now, being the bridge between the two. [0:32:19] JG: Something like that, yes. [0:32:19] PG: Because I was wondering, like, for example, as you said, that, for example, type, that they're one version ahead, you're one version behind, then you have to work with TypeScript. It seems that there's always somebody chasing somebody. So, in this So, in this case, ESLint being the kind of in the leading package and you're more conforming to whatever they change and not vice versa. So, maybe you being the bridge in both is going to make it more equal. [0:32:41] JG: I hope to do that. I hope to take on more of a role of that as time goes on. It's hard because for starters, I just joined ESLint this year in 2024, early January. I'm also not on the technical steering committee. They were referred to as what we refer to as maintainers. I'm just a committer, so I'm not the most influential person in the room. I'm new to this, I'm still learning, I'm still ramping up. Also, open-source projects are not corporate funded teams. We're not TypeScript. We don't have the backing of Microsoft. We're a true independent project, both of us are. So, we are very limited resourcing and budgeting for even the bare necessities of triage and GitHub issues, let alone planning for the future and collaborating with ecosystem partners. I mean, when you're a project like ESLint, that touches basically every JavaScript project in production, or at least a super-majority of them. It's really hard to find the time to do the due diligence that one would ideally want to do when working with partners or releasing new versions. [0:33:40] PG: So, you work on open source full-time now. In the past, you have worked at Microsoft, you have worked at Codecademy. So, how is the life of an open-source developer? And how is it different than your life when you were an employee? [0:33:52] JG: First of all, I appreciate you pronouncing Codecademy correctly. There's no A in the middle. That gets a lot of people. [0:33:58] PG: There might be more. [0:33:59] JG: Yes, you got it right. Most people - [0:33:59] PG: It might be a Slavic accent. Coming into that, just pronouncing a single word that's written in a single letter. [0:34:08] JG: As someone who works on linter is a lot of the time I appreciate the precision and accuracy. The way that I try to introduce the concept of working open source to people is imagine as a company gets bigger, fewer and fewer people around you, you get more and more separated like you're working at like Codecademy was when I was there, so let's say like 200 people scale. You know everyone there. You know all the developers. You might not work closely with all them, but you know them. Then you get to like a mid-sized company where you know of most of the teams maybe, but you don't work with a lot of them. And then you get to like Microsoft or Amazon where their internal politics where like entire organizations get shafted because someone had a bad year or something. Then go even further beyond that. That's what open source is like. No one knows anyone. There's no core organization. There's no goal. Thank God we don't have stockholders to appease because we have no money. But it's just you're out on the open. There's no structure. You got to do everything yourself. If you're lucky, you'll find a few people you can consistently work with who you also enjoy working with. [0:35:10] PB: It sounds more like being a founder of a bootstrap startup than working at a large, because then it's still you're kind of alone in this world, in this universe with all the products and requests. [0:35:22] JG: The loneliness of a founder with the backing money of a charity. [0:35:25] PB: And what is the best part? [0:35:27] JG: The best part is that I get to work on the stuff everyone uses. Whenever I, let's say, merge a feature in TypeScript ESLint, something I'm excited about, that means everyone who is linting TypeScript with ESLint gets to benefit from that feature. If I fix the real pain in the butt with documentation or onboarding or something, that's making it better for whatever number of thousands of people. I really like that. I think it's very satisfying. I'm truly deeply satisfied and happy with my work in a way that I rarely got to be with corporate work, not appeasing the stockholders or one specific segment of people. I'm working for everyone who's a dev. Then, it's also really good for me professionally. I've made a bazillion connections in industry and other open-source spaces. I've gotten to speak at conferences because I have a really flexible schedule and work and work on tooling that everyone should care about in the TypeScript world. So, if and when I go back into corporate life, when I want start a family and have a real paycheck, and health insurance, then I will have been benefited by doing this. [0:36:27] PB: What is the most challenging part of maintaining open-source projects? Because obviously, you meet all those great people, but then would you have issues with managing their requests, any expectations that those people that use this, and they use your work that they have? [0:36:43] JG: Yes, I think the general umbrella is that the industry as a whole doesn't really understand open source. It's getting slowly better at it. Some people, even some companies do understand it pretty well or very deeply. But we get a lot of people who send us a screenshot of their ESLint error and no other context. They won't even put alt text on which is, an accessibility no-no. "What if I was blind? Would I be able to help you?" And then they get mad when we ask them for, "Hey, I have no idea what the hell you're asking me for. Can you provide any context in such as what was asked for in the contributing guide that you marked as having read as part of the issued checkbox?" That's very frustrating. It's off put or offset by the positivity that a lot of people do respect and appreciate open source and the maintainers behind it, which makes me feel good. But it can be very isolating to have to deal with hordes of crap and then not having a manager or dedicated company mentor or team around me to just be kind of floating off in the deep end for years. [0:37:42] PB: And having to deal with it indirectly. Because at the same time, it's an important work, right? Because you're building the fundamentals of a lot of modern web applications in the JavaScript, especially if you work within stuff like ESLint or TypeScript Lint or any other open-source library that's used quite widely. And then you have people who come and they got it for free, and by providing a description not detailed enough will actually steer you away from pushing more crystallized thoughts into this code base which then later will be propagated to a lot of millions of projects and you're just there with the screenshot trying to figure out what that person who is angry is trying to say. [0:38:21] JG: Yes. The fun part of that, "fun", is that every angry person contains a deeply satisfied user or at least the potential for that on the inside. If I respond currently to someone who just posts his screenshot angrily or similar bad behavior, I'm well within my rights. We have a contributing guide. There are enough resources. You should know how to do this. GitHub even has things. But if I respond kindly, if I link to this specific part of the contributing guide they say they've read, you can tell I'm bitter about this, then oftentimes that converts them into someone who's first apologetic for being rude and then like actually a proponent of the library and contributor. So, depending on how much emotional energy I have on a week. I might put more effort into these kinds of user reports. [0:39:03] PB: Doing marketing through customer-like developer service almost. [0:39:08] JG: Yes. GitHub issues is a marketing funnel. [0:39:12] PB: Yes. I used one library that I don't want to name, but the very useful, excellent code. The maintainer is very, very good developers. However, asking for anything on their internal forums, it's just, it's scary because this main maintainer who's an excellent engineer, whether you would just say, "Yes, just go search on Google." [0:39:31] JG: RTFM, read the effing manual. [0:39:35] PB: Pretty much, and in a very kind of angry phrasing. So, I never asked anything, I just found a lot of other people that asked and they were just like put down a lot. [0:39:44] JG: That's not a good open-source maintainer. [0:39:46] PB: No. However, the library is actually excellent. So, they use it widely. Also, with, as you said, that if something goes wrong as a founder of a small video conferencing business, also I knew that I won't get praise every day. "Oh, this is great." But as soon as something breaks, and I start getting emails, "Excuse me, this doesn't work." I'm like, "Okay, this is actually useful, what I made." So, at least you have this - and this negative feedback actually being a positive feedback in this case. I was wondering, how do you resolve any conflicts and arguments within open source projects? [0:40:19] JG: It's tough. You don't have a remediation team or HR to fall back on. Fortunately, open-source kind of selects for people who are there for the sake of being there. You get a lot of people who do first contributions because they want to bolster their LinkedIn, get that first job, build a name. But people who are consistently there are, for the most part, pretty passionate about it. So, that passion comes with some fiery emotions sometimes. But it's hard to be an open source maintainer with other people long term, if you don't have the ability to put your passions aside, your personal context aside, and try to deeply understand what other people are doing. So, I highly recommend anyone who's a developer and has the time to read books on this stuff, read - I got three books in order for y'all. How to Win Friends and Influence People, updated for the 21st century, the original version I've learned the hard way, it's not a great book to recommend to people this day and age. Radical Candor. And Nonviolent Communication. Those three books are a huge foundation of how I approach problem-solving and consensus gathering online. The general gist is you can't argue with someone or you can't even debate them. You shouldn't argue, you should discuss until you truly understand what they're trying to say. So, until what they're trying to get to and the reasons behind it is publicly in a GitHub issue, or if you're having a private discussion in the chat, there's no point to try to throw your opinion at them. Because what do they care about your opinion? You don't even know what they're trying to say. And I found that 99 % of the time, if we're having a disagreement on a rule, us figuring out what each other is actually looking for and what the reasons behind that are, that will turn that discussion into something productive rather than a heated debate. [0:41:58] PB: I think this is very wise. I'm definitely going to have a look at the books as well. I was wondering, apart from recommending those three books for any future developers who might get into open source, but I think this is useful more in general life than on the open source. What other advice would you give for any developers that may be for boosting their LinkedIn profile even, or out of passion that they want to get into open source and contribute? [0:42:22] JG: I'd say there are no bad reasons or very few bad reasons to contribute to open source. If you're just in it for the money, whether that's development or open source, well, hopefully you're just in development for the money. Open source doesn't have a lot for most projects. Great, fine. That's totally valid. We live in a capitalist world. Sometimes you got to do what you got to do. Actually, oftentimes. I'd say I slowly ramped into open source. I did not just learn to code and then boom, I'm a maintainer. I got a "real job." I had internships first and corporate jobs and those taught me a lot of really good skills, how to work with people, how to code, how to learn a new, whatever, tool, framework, architecture, language. Building up those skills first is immensely useful. So, if you have a job and you're thinking of quitting and going open source, it's a risk. Make sure you have money first, but also make sure you've gotten what you want and need out of the job. If you don't have a job and you want to get a job and to use open source as a way, great. Open source can be a fantastic way to bolster your LinkedIn, your GitHub, to learn new skills because open source projects can oftentimes be using different tech than what you're used to. I'd say to try to deeply understand as much as you have time to, whatever it is you're working on, don't just like go to a project and like, I don't know, throw some code there on the pull request and then see what happens. Actually, read the project's documentation, see previous pull requests, like how do people approach writing tests in this project. It'll save you and the maintainer a lot of time if you do your due diligence and read a lot and try to do a good job and understand what you're working on and then ask questions, informed questions, whenever there's a gap, that really helps. [0:44:02] PB: So, I think what you mentioned with not just making like a random feature request with some code, that you think without understanding everything. I think that occasionally you have developers who are great developers, but a developer on a project who understands the code base very well, might be very valuable even more than somebody who's very smart can come and quickly fix something or try to push some smart feature without understanding the entire concept. Even if it's not done well, the project, if it's not organized well, there's still some knowledge that developers need to have in order to navigate quickly through it and to also have the intuition on, for example, if I push this feature, is this going to break something else? Is this going to be out of the conventions that we have decided to use? Or for example, is it not becoming a Frankenstein project versus something that's coherent and unified? [0:44:53] JG: That's important. [0:44:55] PB: I wanted to come back a little bit to this is my own personal question out of curiosity, because you have published the Learning TypeScript book. I was wondering, what's the process of releasing a book about programming? What was your work process? How long did it take you? And are you still updating it? What's the story behind it? [0:45:12] JG: Yes. I'm still updating it. Whenever someone posts Errata, which is the O'Reilly common book term for typo, or this is unclear, I'll update, which then can go into electronic version, unfortunately, not the print version. Although I would two in a couple of years, maybe look at - [0:45:27] PB: It's like a PR, basically. It's like a bug. [0:45:30] JG: Yes, it's actually a Git repo, a Git repository on the inside. So, I send commits in. It's not GitHub, it's like an internal thing. But yeah, similar to how one might scaffold out a new project architecture or a course online, you start with the very broad stuff and then get more granular over time. When I first started working on the book, it was a O'Reilly who reached out to me because at the time, I was already kind of known in open source and with my blog, and giving wacky talks at TypeScript conferences. So, they wanted a book very broad sense to teach TypeScripts, like the new Learning TypeScript give or take book. They wanted that because there was an opening in the market they hadn't released one in recent years. TypeScript, as any programming language evolves every few years over the years. So, I was I was well position at the time I was working at Codecademy to, take the teachings from being on a dev team and helping Codecademy with a few courses to write a book. So, that was step stage one. What is the book? Stage two. two was like, you what are the inputs and outputs? We decided the input would be you need to know JavaScript somewhat. You don't need to be an expert, but like it's really hard to teach TypeScript a super set of JavaScript. If you don't actually know JavaScript, that's a much larger book. The output should be, you don't need to be an expert on TypeScript to use it, but you should know how it works. Like what are the philosophies? How does the type system fundamentally work? Then, a lot of the important and some of the useful, but maybe not as common features. That was stage two. Stage three out of four was setting up one of the chapters, should arrays come before objects and/or functions? When do you teach conditional types? Do you even teach conditional types, and so on? So, we kind of set up what computer scientists would call a DAG, directed acyclic graph, what teachers would call a learning flow. By the way, DAG is a concept, so useful for teaching. Then stage four was, it took about most of that year, go through each of those chapters in order and write them. It's like writing a lot of long blog posts over the course of a year with the added benefit of having a very useful editor and O'Reilly team to support me in that. [0:47:30] PB: It's amazing. So, it's becoming a thing slowly the go-to for learning sorry in TypeScript at the same time. [0:47:39] JG: It's one of them the TypeScript documentation, the TypeScript handbook is fantastic free open source. It's a starter. It doesn't go deep. It's not as well structured as like a book or online course would be because it's a handbook The nature of books and programming is that as soon as you think you're on top someone else comes along. Matt Pocock who is a very well-known and very, very good TypeScript educator is, I think he just recently released his, the free total TypeScript book, which is another format I recommend. Not every format is for everyone. I personally can't stand learning on videos or through lectures. So, books for me, but other people might prefer his like course or his videos. So, I am currently the most popular print book for Learning TypeScript that I know of, or at least like the biggest mind share in the conferences I talked to, which is admittedly a very skewed and biased perspective. [0:48:25] PB: How did you select the parrot? [0:48:27] JG: You know what? I didn't. And I would have loved more say in that process. I was relieved. They don't tell you what it's going to be. They ask you, "Hey, we might not listen to you, but do you have any requests?" I just wanted a parakeet because I grew up with a beautiful green budgie named Emeralds. He was the cutest thing ever. So, I was relieved that it was a pretty bird. But there's a secret cabal deep within O'Reilly that even my editors didn't have access to that chose that. [0:48:54] PB: I was wondering, it's like they call you up and they ask, "Well, what's your favorite animal?" It's like, "I love boars." I think there's one book with a boar in the front. [0:49:01] JG: Yes. I mean, I feel bad for the Rust people. Their stuff is all crabs. [0:49:05] PB: I would again. [0:49:07] JG: Imagine. [0:49:07] PB: I'll have to check it out. [0:49:08] JG: Crabs. I'm never I'm never going to throw shade at another ecosystem, but I'll throw shade at the Rust crab. That's a weird mascot to have as a whole thing. [0:49:17] PB: Seafood oriented. I wonder how many people watch podcasts on the video versus on just audio. So, for whoever is just listening, Josh is looking for the parrot. [0:49:29] JG: I'll leave this as an exercise for the reader. The parrot's on the front cover, but there's an explanation somewhere in the book I can never remember where of, like actually the way - the reason why O'Reilly does this is like every animal is like something important. Like, ah, I found it. The animal on the cover Learning TypeScript. It was a sun conure. Aratinga solstitialis. It gives a little explanation. A lot of the animals are like endangered or threatened. So, it's a nice thing they do. [0:49:52] PB: Definitely, it is. Actually, I quite like the cover. I was wondering, with all the experience and the detailed knowledge about both TypeScript and JavaScript that you have. Where do you see evolving within, let's say, five years? What are the biggest challenges with not just linting and TypeScript, but within the entire ecosystem that you think we are facing? [0:50:15] JG: The JavaScript ecosystem is big and wide and deep enough that there are multiple areas of advancement. One that I don't personally think about a lot, although is very big and important is like the top of the scale for UIs for like React and Solid and Angular, that these UI, previously libraries, now really large frameworks and meta frameworks are getting more and more expansive and better and better at doing their job. If you like at React server components or the equivalents and other UI things, it's just so far ahead of what we were doing even five years ago, pre-hooks even. But for specifically the areas I work in, like, JavaScript, TypeScript tooling, I think there's already a big push for performance for rewriting things in faster and more memory safe languages like Rust. So, faster than JavaScript, more safe than C++. I think that the ecosystem tends to fluctuate between this tool can do everything, but it's a pain to configure, and this tool does everything with relatively fewer configuration options, so it's harder to extend, and we're moving towards the easier to configuration, one tool like a Biome or XC that does everything. But then like their plugin models are not as first class as like an ESLint, and another analogy would be like moving from Webpack to Vite. So, it took a little while for Vite to get as community embraced, as pluggable as Webpack, but it's so much nicer as by design. So, I think that hopefully we get more competition in the ESLint liting ecosystem. I really don't like that TypeScript ESLint is the only one that is typed rules. I'm happy to continue innovating here to push forward things like project service and our recommended stylistic and strict pre-second figs. We just merged earlier this summer a rule that enforces the golden rule of generics, which I leave as an exercise for the listener or viewer to go find on our docs, no unnecessary type parameters. But it's always in flux and I look forward to seeing, you know, faster, easier to configure tools competing with us. That would deeply make me happy. [0:52:19] PB: Personally, for you, what are your long and short-term goals now within the open-source space and any fun, cool projects that you kept in secret, maybe, that that you're about to reveal? [0:52:33] JG: Nothing secret. I can't stand working on secret projects, in part because I'm too braggadocious. In part because it costs more on hosting services to keep things private. For ESLint, I'm still ramping up on the team. I really want to get deeply familiar with it and then be able to help with the rewrites. For ESLint specifically, I want to ramp up on it, become a deeply committed member of the project and understand how it works and then help with the rewrite. For TypeScript ESLint, v8 stable, get the project service stable. We have a backlog of issues suggesting like new rules and niceties. So, I really think for us, our excellence is providing you the best set of linting typescripts, lint rules imaginable. For example, the no unnecessary type parameters one, to really, really be able to enforce and push forward best practices in the TypeScript world. Other linters will have to follow suit. Once they have feature parity with us and have different architectures, they'll be able to innovate too. Honestly, they already are in ways that we haven't thought of or don't have a good positioning to, which is I think really good for the ecosystem. Long-term for me, I put a blog post on this beginning of each year with my intent. And then at the end year, how that intent went, which is never as intended. I want to do those things. I want to continue to push forward my TypeScript template. I have a little thing called create TypeScript app that can create a new really, really nicely configured TypeScript just like little CLI or node application with all the bells and whistles for tooling that one could want, TypeScript and Knip and all this stuff. I want to turn that into like kind of a generalized creator template so that someone who's making like a create Next app or create React app or create TypeScript app could build on this shared foundation. I actually co-own the create package on NPM now. Thanks, Nate from Bercel for letting me be on that, and then I also want to make a linter for GitHub issues and pull requests and discussions. I have 15 different actions I use to like, "Oh, is your issue adhering to the format? Is your pull requests addressing an issue that's marked as, whatever label you want except in pull request?" It's just such a pain to set those up individually. [0:54:42] PB: Would you see the open source and the PR linter to work mostly for open source projects, for open projects? Or would you see this working within companies as well? [0:54:52] JG: I prioritize open source selfishly and theologically. But I see no reason why I would restrict it from companies. I mean, architecturally, it's a lot harder and a lot more different to write like a GitHub pull request action bot verifier, especially if you want to start applying auto fixes, then GitHub pull request permissions come into play and you might need a hosting service or serverless app or something. So, maybe a profit model would be to charge companies or just charge private repos for this. I don't know. I haven't even started working on this. It's months down the line I'll be lucky if I start working on it in the fall at this point. [0:55:27] PB: I just find the most pedantic CTOs of any companies and just preach it to them to make sure that all the PRs that their developers push. [0:55:35] JG: Oh, yes. [0:55:34] PB: Screenshot description, everything, video. [0:55:38] JG: I've seen some pedantic CTOs. I don't encourage that behavior, but if I can make money off it. The last thing I should know is I'm also co-organizing a conference called SquiggleConf, which is happening in October, October 3rd in Boston, for excellent web dev tooling, things like TypeScript and Go and Zig and Rust and all this stuff. That's a lot of time too, and I'm really excited about it. [0:56:00] PB: Does it have any link that we could put in the description? [0:56:02] JG: Yes, squiggleconf.com. [0:56:04] PB: Easy as that. Thank you so much for your time. That was very interesting and looking forward to also the conference and recordings. [0:56:12] JG: Yes, no, thank you. This was a great interview. Cheers. [END]