TypeScript, ESLint, and TypeScript ESLint with Josh Goldberg - JSJ 605

Josh Goldberg is a full-time open-source developer. He begins by sharing his developer experience and what he is currently working on. He joins the show to talk about "TypeScript, ESLint, and TypeScript ESLint". He dives into what this is all about, how these projects work, how they relate to each other, and much more.

Special Guests: Josh Goldberg

Show Notes

Josh Goldberg is a full-time open-source developer. He begins by sharing his developer experience and what he is currently working on. He joins the show to talk about "TypeScript, ESLint, and TypeScript ESLint". He dives into what this is all about, how these projects work, how they relate to each other, and much more.


Sponsors


Socials


Picks

Transcript


Charles Max Wood (00:01.544)
Hey, welcome back to another episode of JavaScript Jabber. This week on our panel we have Dan Shapir.
 
Dan (00:09.213)
Hi from Tel Aviv.
 
Charles Max Wood (00:10.984)
Now in Technicolor, we also have Steve Edwards.
 
Charles Max Wood (00:18.592)
I don't know if Steve can hear me. Yeah, maybe, maybe he's frozen.
 
Dan (00:18.748)
Do we have Steve Edwards?
 
Josh (00:19.778)
Do we? Oh.
 
Steve (00:22.879)
Yeah, I froze. Sorry. I'm gonna pause my upload. Okay.
 
Dan (00:29.84)
Oh, you're, yeah, Chuck, you may need to pause his upload for him.
 
Steve (00:31.187)
My wifi sucks here, yeah, I think so.
 
Josh (00:33.346)
know.
 
Charles Max Wood (00:35.904)
Sounds like he did it himself, but.
 
Steve (00:37.643)
Yeah, I did.
 
Dan (00:39.06)
You want to start all over from fresh?
 
Charles Max Wood (00:42.092)
Sure.
 
All right, here goes. Hey, welcome back to another episode of JavaScript Jabber. This week on our panel, we have Dan Shapir.
 
Dan (00:54.1)
Hey from Tel Aviv!
 
Charles Max Wood (00:55.836)
Now in Technicolor. He's just got a new computer with a new camera. It's so pretty. We also have Steve Edwards.
 
Dan (00:57.609)
Yeah.
 
Dan (01:01.444)
Exactly. Yeah, I'm so pretty.
 
Steve (01:04.978)
Hello from the warm desert area of Arizona.
 
Charles Max Wood (01:09.856)
Nice. I'm Charles Max Wood from Top Bend Devs. I just got back from Amsterdam. We have a special guest this week and that is Josh Goldberg. Josh, you want to introduce yourself? I don't know if we've had you on before.
 
Josh (01:18.71)
Hey everyone, I just got back from.
 
Josh (01:23.87)
Yeah, I don't know. I don't know if you have. But hi, I'm Josh. I work in open source full time, mostly in the TypeScript ecosystem. I was actually just in Amsterdam right before Chuck and then in Timisoara, Romania. So I'm glad to be back home in Philly. I am tired.
 
Dan (01:37.748)
Timah Shuar is lovely. Amsterdam is also lovely but yeah that's obvious.
 
Josh (01:39.48)
Yeah.
 
Charles Max Wood (01:42.556)
Yeah, yeah, I had a good time. Yeah, I was there for Railsworld. I don't know what you were there for, Josh.
 
Josh (01:50.634)
React Live and then prior to that JSA IE in Dublin. So I'm post-conferencing right now.
 
Charles Max Wood (01:52.073)
Oh, there you go.
 
Dan (01:55.296)
Oh, yeah. I thought I think I might have already watched your talk from there.
 
Charles Max Wood (01:57.824)
Wow.
 
Josh (02:01.787)
Oh, great.
 
Dan (02:03.749)
Or maybe, I don't know, maybe I'm confusing it with some other talk. It seems a bit, you know, quick for the talk to be up already. I'll need to check.
 
Charles Max Wood (02:11.804)
Yeah. So anyway, the story here is basically that I figured out that I wasn't checking the DMs on the JavaScript Jabber Twitter account. And Josh had told me about interesting stuff that he was doing on that same account. And so I got on and it had been a few months and I was like, no, this is cool. We should get you on. So Josh, yeah, welcome to the show.
 
Josh (02:32.29)
Thanks for having me.
 
Charles Max Wood (02:33.896)
Yeah, now you're talking to us about the, what is it? It's the TypeScript, NS, or no, ESLint, something, right? Am I in the right ballpark?
 
Josh (02:47.978)
You are, yes. I like hearing people suffer and struggle with our naming, but yes, it's TypeScript ESLint, the tooling that lets you allow, pardon me, the tooling that allows you to run ESLint and prettier and similar TypeScript code.
 
Dan (03:01.201)
Can we? But that...
 
Charles Max Wood (03:01.456)
I should have just confidently said that, but I didn't. Ha ha ha.
 
Dan (03:05.536)
Can we slightly digress before we go there? Because you mentioned right up front that you're 100% into open source. And I'm really curious about how, you know, what's it like? How are you making this work? What's life like for a, what's life like for being, you know, for someone who's a hundred percent in open source.
 
Josh (03:23.136)
making it work is a strong phrase for what I do.
 
Josh (03:32.062)
It's very scattered, but I really enjoy it a lot. And it's less different from my old full-time jobs than I would have thought. Um, instead of working on tooling projects, work in general for a specific company or set of companies, like when I was doing consulting, instead I work on GitHub projects, which may or may not have other people working on them or even using them. So my day to day is a lot of going to my GitHub notifications, blazing through a bunch of issues and pull requests, uh, doing.
 
dev marketing and dev rel on Twitter and so on. The money is not nearly as good, but I really, really like what I do. And I think I have a positive impact on the world and community, I think. So I'm having a great time.
 
Dan (04:15.437)
where is the money coming from if I might ask.
 
Josh (04:18.858)
A little bit from GitHub sponsors. I have a personal sponsors page. TypeScript BSLint itself has an open collective, which is quite a bit more money than my personal. Once in a while, I'll dip into consulting if I start to worry about the money. And then also I wrote the learning TypeScript book from O'Reilly, so that gives me monthly royalties too.
 
Dan (04:36.768)
Oh, that's really cool. An author. Published author.
 
Josh (04:41.703)
Yeah, yes, a lot of people reference books on TypeScript, and it's nice. I think mine is currently the main one that people use to get into it if they haven't written any TypeScript or any other language beyond JavaScript before. So I'm very proud of that.
 
Dan (04:57.084)
I'm curious, are you teaching TypeScript to people that you assume already know JavaScript or is it teaching TypeScript as a whole new language?
 
Josh (05:06.75)
It's the former, yeah. I assume you have some level of JavaScript. It doesn't have to be super advanced. You don't need to know things like symbols and disposables, but pardon me, the new using syntax. The art of teaching TypeScript is trickier, much trickier if the person doesn't already know JavaScript. It's, I think it's possible to write a book that teaches both, but it's much quicker and I think more clean to assume it been a JavaScript first because that's how TypeScript works. It builds on top of JavaScript instead of replacing it.
 
Dan (05:18.08)
Hiya.
 
Dan (05:35.476)
So if someone were to ask you basically, let's say, I want to get into front end software development. I don't know any programming. I want to do it myself, you know, not going to a bootcamp, whatever. Would you recommend to them to first learn JavaScript and then learn TypeScript?
 
Josh (05:53.43)
That is my kind of default starting recommendation. I have worked with people who just went into Typescript first. It's not an impossible path. Um, there's a Twitch streamer, Jen Junot, who is going through my book now with me. And she knew no JavaScript beforehand, but for the most part, I really recommend people try to learn one thing or area of things at a time, in this case, learn a programming language, learn the concept of for loops, if statements, functions, and so on, and then also add on the concept of a type system on top.
 
That being said, TypeScript is really useful for people who are learning to code because it gives you a lot of really nice hints and suggestions and tooling before your code crashes annoyingly. So it's not a one size fits all. I just have a general starting recommendation.
 
Dan (06:35.004)
Yeah, it's interesting that when my son studied computer science in university, he's just wrapping up his studies, by the way. They first learned Python as the language for the 101 CS class, and then they moved on into Java to learn about types. So, so in a way they kind of match that sequence that you're describing.
 
And also out of curiosity, you mentioned like multiple open source projects. So it's not just a TypeScript ESLint. It's other projects as well.
 
Josh (07:08.874)
Yeah, but TypeScript ESLint is the main one. I have been working for the last year or so on originally called template TypeScript node package. Now the slightly less annoying name of create TypeScript app, which is a good default starter that can also set up a lot of really good tooling. At time of recording, I am about two weeks overdue for some commitments I'd made to the ESLint project itself. Sorry, Nicholas and everyone else who was waiting and probably impatient with me.
 
Charles Max Wood (07:34.368)
Hahaha
 
Josh (07:36.082)
But for the most part, it's a few big projects, mainly TypeScript, PSL, and then a lot of really small utilities that I've written or joined on that most other people wouldn't have used or heard of.
 
Dan (07:47.36)
So if we're moving back to the main topic of discussion, which is TypeScript ESLint, and you mentioned that you also work on the ESLint project, I guess that means that these two projects are distinct. Can you both describe what TypeScript ESLint is and how it relates to ESLint?
 
Josh (08:09.314)
Yes. ESLint is a project that is the standard JavaScript linter these days. There are other linters out there, but ESLint is the most popular and well-known one by far. In my personal headcanon in terminology, a linter is a tool that runs a set of discrete checks in your source code or rules. Each of those rules checks for one specific issue, such as an unused variable, and then may optionally provide autofixes or suggestions for how to fix if and when it finds complaints.
 
ESLint is really extensible, configurable, pluggable, whatever you want to call it. There are a bajillion plugins out there, things for personal style conventions, framework-specific rules, for example, React's plugin rules. Part of React's rules of hooks are a very popular plugin. But ESLint just works on JavaScript, natively at least. You can add in different parsers, but by default, ESLint only understands core JavaScript syntax. One of the very popular, in fact, the most popular
 
parser, I believe, is the TypeScript parser, which is one of the packages we in the TypeScript ESLint project provide, which, as you said, yes, is a separate project, different GitHub org, different governance, different set of maintainers. I'm a core maintainer on TypeScript ESLint and just so happened to have committed a few times to ESLint itself. So we're very much separate projects. We're not enemies in any way. It's not like we intend to be separate. It's just that they have very different needs as projects. And TypeScript ESLint actually.
 
is much more recent than ESLint itself. Back in the day in the TypeScript community, we had a separate project called TSLint, which was a completely separate implementation of A-Lint-er written solely for TypeScript in TypeScript. And thank heavens, we have deleted all that duplicate code and aligned on using ESLint with extensibility options such as a new parser for TypeScript.
 
Dan (09:59.872)
So TypeScript ESLint takes ESLint, builds on top of it, and extends it to support TypeScript beyond JavaScript. Correct? So it's not like completely distinct. It's a distinct project in the sense that you're working on a separate repo, but it's not distinct in the sense that the two do work together.
 
Josh (10:26.754)
Yes. My only caution with the phrasing there is that we are a parser and a plugin, just like many other parsers and plugins are. For example, there is a plugin that provides you rules for React code specifically, and we are a plugin, among other things, that provides rules for TypeScript code specifically. There are other parsers and we are a parser. So you're still running ESLint. You still do npx-eslint. or similar. It's just your ESLint config.
 
If you want to work on TypeScript code, we'll generally include references to the TypeScript ESLint parser and plugin.
 
Steve (10:59.083)
So if you were to use this, if you're using TypeScript in a project, then you're only using this instead of the standard ESLint when you're installing.
 
Josh (11:08.19)
No, you're using the standard Eos lens, but you're telling Eos lens.
 
Steve (11:10.411)
But I mean, do you need to download that as well as your project? Does your project take care of that in terms of dependencies?
 
Josh (11:16.97)
we don't have any fancy schmancy initializer that wraps around ESLint or does that. You have to install and configure ESLint and then also install and configure us. By the way, I realized this is very annoying and cumbersome to listen to, let alone to do on your computer. No one is thrilled that this is the state of the art and the ESLint team is working on a long-term overhaul that'll make all this stuff easier. But for now, what I've just described is somewhat the current state of things.
 
Charles Max Wood (11:29.629)
Hahaha
 
Steve (11:42.635)
So before we go too much farther, for those that might be uninitiated, could we describe what a linter is? Just to clarify, it is not the stuff that you pull out of your dryer that clogs up your dryer. That's a different kind of lint. I think my thought of a linter definition is basically something that helps you format and make your code nice and neat. Is that a proper way to say it? That's more of a prettier. Or maybe a linter is just sort of to catch some errors and things like that. How would you define a linter?
 
I mean, I know what it is, but I can't describe it, I guess.
 
Josh (12:16.038)
You've activated my trap card. One of the big tirades I've been going on and seeing at conferences is that there are three really common forms of static analysis in the web space today. Linting, formatting, and type checking. I would say that the three are distinct and one should use different tools for each of them. Even if the CLI or wrapper is the same, just the three are separate implementations. The formatter is a tool that looks at your source code and completely reformats it, messes with your semicolons and tabs and spaces and new lines, all that.
 
Steve (12:18.719)
Woohoo!
 
Josh (12:44.47)
Now a formatter is able to be very quick and should be super simple because all it does is reformat your code. It doesn't change your logic. It doesn't catch bugs. By simple, I mean from the user side, it's actually rather complex to write a formatter, very difficult on the inside. But that is completely separate from the concept of a linter, which runs a set of discrete checks that look for, say, logical issues or stylistic inconsistencies. And fun fact, ESLint has rules that can catch formatting concerns and it has had them for quite a while.
 
And part of the reason why is that when it first came out, there was no Prettier. There's actually a research paper that had to be published for people to figure out how to write a thing like Prettier first. But now ESLint has decided they're going to deprecate the core formatting rules. They're being moved to a separate community authored plugin so that ESLint Core just deals with logical issues and the occasional stylistic rule. Does that answer what you were looking for?
 
Dan (13:39.804)
And you did give before several examples of some of the issues that the linter might catch. I'll give a few more. For example, using let when you should be using const, not using the same variable in an internal and external scope. Unreachable code potentially.
 
Let's see if I can think of some more off the top of my head. If the variable naming, like for example, you're using not camel case, but something else. You should be using Pascal case for classes and camel case for variables. If you're not doing that, are there other examples that I'm missing that are really common?
 
Josh (14:30.662)
Yeah. But before I give my want to note, you bring up a really interesting point that, uh, those are a lot of those are stylistic concerns and developers tend to get a little, uh, rough when we try to force stylistic concerns on them. So a lot of the linter maintainers such as myself, working a little bit less on style things and a little bit more on logical things like catching bugs. That's not to say they're not valid in my create TypeScript app repo. I have
 
lint rules that sort everything for me and do all sorts of style stuff. It's just really hard to get that in a way that people like. But one of the big advantages of TypeScript ESLint running ESLint on TypeScript code is that if you're using a TypeScript code base, you're able to assume that you can use TypeScript's type information. So you can write lint rules that use type information to make really, really intelligent, sharp deductions on your code. For example, my favorite rule is no floating promises.
 
which says if you do something that creates a promise, that promise needs to be handled in some way. It can't just float off into the distance and potentially unhandled process exception crash. It needs to be awaited or have a dot catch or be passed to a variable or something. We also have a rule that detects unnecessary awaits. So if you do something like await some function call, but that function isn't an async function and doesn't return a promise, then you could probably just remove that await. TBD.
 
Dan (15:52.22)
Yeah, it's important to note that it's perfectly legal JavaScript code, that it'll work. It will effectively wrap the result in a promise, as I recall. But like you said, it's effectively pretty useless and probably not what you intended. It's likely the result of some refactoring that somebody forgot to take it all the way.
 
Josh (16:18.75)
Yeah, exactly. And one of the big benefits of a linter, or using a lot of linter rules the way I do, is that when you refactor and you have stuff that's left over, it can catch a lot of those little excess things that might've been okay when they were first written, but because of your refactoring are no longer particularly valuable. So in a sense, one of the many purposes of a linter can be to help you refactor your code and get a little more confidence in your rewrites.
 
Dan (16:41.812)
How about two long or two complex functions? Where would you put that?
 
Josh (16:47.471)
Ooh, probably pull request review. Oh, yeah, if you hate a lint rule, that's a sign that lint rule shouldn't be enabled on your code base. There's a difference between having an opinion and then wanting that opinion to be enforced by a particular part of your dev process. I personally really like small, not tiny, but relatively small files, functions, and so on. But it's roughly impossible to make a lint rule that can delineate a fine line,
 
Dan (16:48.368)
Those are the ones I hate by the way.
 
Dan (16:55.494)
Oh yeah, for sure.
 
Charles Max Wood (16:55.552)
Hehehe
 
Josh (17:15.478)
This is the cutoff, you know, a hundred lines. That's where I draw the line. So I'd say maybe push that into like a soft guidance notes in your team documentation and ask people to check it in code review.
 
Dan (17:26.808)
I'd probably look the rules that I value the most, the rule that I value the most is consistency. So I probably like have like an inverse type process where the tool first analyzes the existing code base, figure out the rules that match that existing code base and then enforce them, enforces them going forward.
 
Josh (17:50.638)
interesting. This feels like it's better suited for a tooling that is not based on hard measurements, but on vibes, on general soft thoughts. So actually, I really hate to bring up AI, because we're talking about tooling that does is not a good suit fit for AI. But yeah, like the human part of things, what you just described, I think is where I put that concern.
 
Charles Max Wood (18:06.248)
Hehehehehehe
 
Dan (18:12.04)
It's like, I see some code, I'm one of those people that prefers functions, the function keywords for named functions, but I see a lot of code bases where people use arrow functions for named functions as well. So they would have like const x equals an arrow function, and that's the way they declare functions. And even though I dislike this approach, if that's the way the code base is written,
 
That's how I will write my code. So because otherwise you're bringing up, you know, somebody who reads the code later on, starts asking themselves, why is this code written differently than the rest of the code? Does it indicate some behavioral or functional difference that often doesn't actually exist and so forth? So consistency is the number one concern. So a rule like that, like looking at the code base, figuring out that code base, like mostly uses arrows for name functions,
 
and then enforces that going forward. That would be cool for my book, but I digress.
 
Charles Max Wood (19:17.324)
Well, in some of the linters I've used in other languages, that's effectively what they do. And so when they enforce it though, they have the option to fix it, right? Which is a format or not a linter, according to what Josh is telling us.
 
Dan (19:26.664)
Yeah.
 
Josh (19:31.326)
Well, well, it's a very difficult line to delineate. In theory, formatters would only do things that don't change your AST or abstract syntax tree, the representation of what is actually in your code file. But there are some concerns that do have a different AST, such as a named function versus an arrow function versus and so on. But like they don't really change your code. So if you look at the code and it doesn't use any of the features that would care about which one you used, you could probably fix it. But.
 
Dan (19:59.272)
Yeah, that could be really challenging to figure out in some cases, because the hoisting rules, for example, are different, and it might be really tricky to make sure that you're not introducing bugs if you try to automatically reformat the code in that way.
 
Josh (19:59.602)
Generally, it's hard.
 
Josh (20:19.827)
Yeah. ESLint rules can alternately either or both of fix and suggest. They can provide a fix that is safe. It is marked as unless we have a bug, this is okay to dash fix automatically. They can also provide suggestions. Like the unnecessary await rule I mentioned will provide a suggestion for removing the awaits but it won't actually automatically do that. It's not a dash fix.
 
fix because that actually does change your code slightly. And maybe you had a reliance on that extra process ticked from the unnecessary way and fixing it would actually destroy your entire application. Who knows?
 
Dan (20:54.624)
I have to ask though, given that, well, AJ likes to say, who's not here on the show today unfortunately, likes to say that TypeScript is a superset of a subset of JavaScript. But effectively it is in most cases a superset. Why not just use TypeScript ESLint? Why do I even need ESLint? I mean, why don't I treat everything as being
 
Josh (21:07.959)
Hahaha
 
Dan (21:23.336)
TypeScript sometimes with missing types.
 
Josh (21:28.194)
Quick question.
 
Dan (21:29.36)
Especially by the way, if I'm using, let's say, J-Stock inside JS file.
 
Josh (21:35.17)
Great question. So we had that. That's what TSLint was. I was a maintainer, not a creator, but a maintainer on TSLint. But the problem then was that you have a lot of people who still do write JavaScript without TypeScript and a lot of tooling built on JavaScript, not TypeScript. Because JavaScript is an open standard, ignoring the fact that some company happens to open the trademark, so we have to call it ECMAScript. JavaScript is the thing that runs in browsers. Whereas TypeScript is one example of how one might extend.
 
JavaScript. It is not a standard. It's owned by Microsoft. Fun fact, did you know Microsoft used to have a not stellar reputation among developers? I blows in the mind. So we really don't want to yeah long ago. Yeah, I don't yeah
 
Charles Max Wood (22:13.653)
good old days.
 
Dan (22:15.36)
Been there, done that. Embrace, extend, extinguish.
 
Steve (22:18.167)
I am shocked, shocked.
 
Josh (22:22.41)
Yeah, so even if Microsoft was perfect, if every developer at the company was as wholesome and wonderful and smart as Satya Nadella, their current CEO, who people tend to like, myself included, it's still a specific company's thing. So we don't want to build tooling that forces everyone to be writing one company's specific language. In fact, I am looking forward to competitors to TypeScript because TypeScript is a decade plus old project and it has limitations as a result of that age.
 
And I look forward to the next round of cool stuff we can do. But anyway, I digress. Yes, we used to have TS-Lint. And then, because we still needed this stuff to work on standard native JavaScript, you'd have two implementations of everything. Two implementations of your linter, two implementations when we added rule fixers, two implementations of the React rules of hooks, the ESLint plugin and TS-Lint for React. It was a pain in the butt. So now we've duplicated a lot of the code. And.
 
If they ever diverge, it makes it harder to swap back and forth between if you convert to or from TypeScript and JavaScript. And before you ask, why would you ever convert from TypeScript to JavaScript? Well, that happens once in a while. So, yeah. Yeah.
 
Dan (23:27.773)
DHH for the win!
 
Charles Max Wood (23:29.152)
Ha ha ha!
 
Dan (23:31.408)
Also to an extent SvelteKit, although the story there is very different. Svelte, sorry.
 
Steve (23:35.046)
Yeah, Svelto or so, yeah.
 
Josh (23:37.322)
So that's a whole other topic. SvelteKit, they're still using TypeScript. They're just using a different syntax for the types. Yeah, exactly.
 
Dan (23:41.98)
Oh yeah, we just with JS doc. Yes, exactly.
 
Steve (23:45.107)
Well, and they still support it on the front end if the users want to use it. It was just in their core that they made the changes.
 
Josh (23:50.526)
Yeah. I would even say almost every JavaScript developer today, even if they never touch TypeScript, is still benefiting from the language because it's built into editors such as VS Code.
 
Dan (23:57.776)
Oh yeah, yeah for sure.
 
Steve (24:00.031)
Well, yeah, I mean, I'm a view user myself. I did the views on view podcast and view three was all written in TypeScript from the ground up.
 
Dan (24:06.344)
No, and, but it's beyond that. It's the browser DOM, uh, the, uh, node API's, uh, express whatever, they all come with TypeScript bindings these days. So, and you know, the type definition files and you're benefiting from TypeScript, even if you're not using TypeScript at all. Like when that all croffle, you know, on, on the Twitter spaces, X, whatever happened, I kind of, uh,
 
shit tweeted that my ideal development environment is I'm doing JavaScript and every other developer in the world does TypeScript because then I get the total freedom and everybody else has to, you know, provides me with all the type information that I might need.
 
Josh (24:54.606)
That's really funny, I like that. I'm sure the reactions you got were polite.
 
Charles Max Wood (25:01.644)
Hahaha!
 
Josh (25:03.33)
But anyway, you asked a question I would, sorry, I keep getting excited and distracted. Yeah, so we had that, it was a pain in the butt, now we deduplicated. So it's the ESLint core and other languages such as TypeScript can be added on. It can be plugged in with stuff such as TypeScript ESLint. You can use TypeScript ESLint on ESLint code. It's just, we provide a lot of niceties that get added in if you have type information enabled on your code base.
 
Dan (25:03.59)
Yeah.
 
Dan (25:28.98)
By the way, again, as an aside, do you have an opinion on the type specifications proposal for ECMAScript?
 
Josh (25:39.126)
I do. I think you can probably guess what that opinion is based on the giant grin on my face. I'm really excited about it. I think that the proposal is really smart.
 
Dan (25:48.06)
Type annotations, that's the phrase, type annotations, not what I said before.
 
Josh (25:53.01)
Sure. It's all the same to me. The general idea is the syntax or annotations, the essentially glorified comment, is something that will be built into JavaScript. So there will be less difference between what you write in TypeScript land and write in JavaScript or run in JavaScript land. But the concept of a type checker is still up to the developer. So TypeScript or one of its competitors, so to speak, or future equivalents can still innovate in the type checking space and perhaps even type syntax space.
 
But if we reach this nirvana in what will presumably be at least five to 10 years from now, likely more, where you can write code that has full TypeScript type declarations inside of it and not have to transpile it into something else to run it, that will be really nice. So I hope that's the world we're moving towards.
 
Dan (26:40.98)
Cool. By the way, Gil Tayyar was a guest on this podcast a while back talking about the ES modules, I think, is one of the people, one of the proponents and one of the people who proposed this to the ECMAScript DC39 committee. But going back to TypeScript ES, ESLint, so can you mentioned?
 
like the some of the rules that are kind of need the type information in order to be implemented like the ones around a weight and the ones around promises making sure that you know there's a catch for every promise. Can you give additional examples of like these kind of types like TypeScript specific rules that need type information in order to be enforced?
 
Josh (27:36.894)
Yeah, and for the viewers who have access to any kind of show note or a search engine, we have it all documented on typescripteslint.io. There's a dash in that name. There's kind of an interesting dichotomy between the two ways that I think about rules. There is the specific to typescript stuff, such as enforcing consistency of whether you use type or interface. That's one of those things where, again, the actual difference is very small. The real important thing, as you said, Dan, is...
 
consistency. And then there are rules that could apply to JavaScript and door types in code, but need the TypeScript type information to work effectively. One of my favorite ones is the one that enforces that you write for loops in the correct way or correct syntax for arrays versus objects. Our rule, no for in array, says don't use the for i in syntax with an array because it's
 
Charles Max Wood (28:08.undefined)
Mm-hmm.
 
Josh (28:31.042)
That actually iterates over the properties of the array, and it has these weird edge cases, and it's not great. You want to use for of. But the only way to know whether the thing being iterated over in any particular line of code is an array is to use the type information. Because in theory, you could write this rule with just the single fly on a bind, but if it's like the result of a function that's been imported from somewhere else that imports from a node package, yada, it's impossible to know what it actually would be unless you have the type.
 
Charles Max Wood (28:34.162)
Right.
 
Dan (28:58.368)
So here's an interesting thing that occurs to me, and correct me if I'm wrong. Seems to me that when applied to JavaScript, ESLint is very local. You look at the specific JavaScript code inside the function. When you're thinking about TypeScript, you're thinking about types of other functions.
 
and functions that might be declared in other files. And TypeScript doesn't have like, you can see like.h files or stuff like that. It's the actual source code of the file. So a change in one file could impact the correctness of lots of other files. Something that doesn't exist in JavaScript that I can think of maybe.
 
does, I can't think of when it might exist. Maybe stuff with dynamic imports, I don't know, or stuff like that, or any imports, like that you're importing something from a file and then you remove the export that maybe could impact other, that's a change, adding or removing an export, that might be a change that impacts other files like with JavaScript.
 
But other than that, I'm hard pressed to think of any case or scenario in JavaScript where changes in one file might impact the correctness of other files that you can check.
 
Josh (30:36.572)
Yes.
 
Dan (30:36.724)
but that's not the case for TypeScript if I'm thinking about.
 
Josh (30:41.534)
Yes, you've hit one of the focal points of my life pain here, that ESLint was originally designed assuming that the AST, representation of a file, a single file, along with your configuration, is all you need to lint that file. That is no longer the case. There are quite a few pain points because ESLint was designed with one way in mind, and now we've gotten to this more complex way. ESLint's cache.
 
mechanism that it comes with doesn't understand the concept of one file changing might invalidate the cache for every single other file. And then, yeah, it's, there are some performance implications of this that mean that running ESLint with type information in your editor and or on the CLI is not as fast as it could be because of the APIs that we and the parser land are given are a little restricted. So, yeah, the way we actually, I'm sorry, go ahead.
 
Charles Max Wood (31:16.606)
Mmm.
 
Dan (31:34.788)
Before you delve into that, you mentioned a term that might be worth an explanation to some of our listeners at least, which is AST. Can you elaborate a little bit on what AST is and how that's being used by a tool like ESLint?
 
Josh (31:50.518)
Sure. By the way, I really hate when I... I have a bad habit of mentioning a term, assuming everyone knows it, and then actually it's a thing 1% of people might know. So thank you for asking. An AST or abstract syntax tree, sounds to me a little more intimidating than what it is. It is a representation of what's in your source code. And both typescriptlang.org and typescripteslint.io have good little playgrounds that can show this. I really like the one in typescripteslint.io slash play. If you have, let's say a variable,
 
Charles Max Wood (31:55.52)
Hehehehe
 
Josh (32:20.466)
Let name equals Josh. That would be represented as a kind of a JSON structure where you have a variable with a name and a value. And then that value is a string and then that string has and so on. And that's what a lot of tooling uses to reason about your code. If we, let's say we're to write a lint rule enforcing let over var, we might look at every variable declaration, see it's child and the tree that is it's kind and check that the kind is let's say, let first var versus con first is using.
 
So that's what tools like ESLint and TypeScript and TypeScript ESLint rules are built on.
 
Dan (32:58.14)
And the fact that it's a tree is because most code in most programming languages are hierarchical. Like you've got a function and in the function, you've got blocks and statements and in the state and you've like, so you can go like a top down kind of a way of building a representation of the entire code. And it's kind of the, the meaning of the code with the cement, with the kind of the syntax being stripped out in effect.
 
Josh (33:28.638)
Exactly, yeah. It's abstract. It doesn't ideally care about formatting, whatever the character indentation is, and it certainly does not care about your type information. It's just the tree describing what's in the syntax. Yes.
 
Charles Max Wood (33:35.605)
Mm-hmm.
 
Dan (33:44.16)
Cool. So yeah, so I guess lint, I guess breaks down the code into an AST and then does what with it?
 
Josh (33:44.534)
So the way...
 
Josh (33:51.858)
It passes that AST to rules. The rules then define a bunch of selectors, each of which run logic when they hit one of the pieces of that tree called a node. For example, let's say the rule that says no var has a selector for every variable declaration where the kind is var, and then the logic, roughly speaking, just reports using the ESLint context, hey, you used a var, don't do that, you silly goose.
 
Now rules can have options about how to report, and then that report might go to, let's say, an editor, or a command line, or some other service. But at the core, you have your AST parsing, used by the parser. Then that parsed AST is passed to rules, and then rules can do whatever they want on whatever subsection of your tree.
 
Dan (34:35.536)
And I guess that TypeScript ESLint needs to replace the parser that constructs the AST because the AST for parsed JavaScript is different than an AST for parsed TypeScript. All the type information, et cetera, that needs to be stored in the tree.
 
Josh (34:56.822)
Exactly, yeah. Interestingly, similar to how TypeScript is roughly speaking a superset of JavaScript, the tree that our parser generates is roughly speaking a superset of the tree that ESLint's core parser generates. We would generate roughly the same tree given this just JavaScript code, but it might also have, let's say an interface or a type annotation or something in there. So we do generate the same tree as ESLint core because core ESLint rules still need to work on TypeScript code.
 
We don't want to have to re-implement everything for a different tree, which is why we don't actually just directly pass back the tree that TypeScript APIs would generate. That's a different format. But there are core ESLint rules that kind of break when given TypeScript nodes. They don't really know what to do with them. So we do, in addition to swapping out the parser, have some rules that swap out ESLint's rules.
 
Charles Max Wood (35:43.305)
So.
 
Charles Max Wood (35:47.86)
So the parsers are things that people write themselves. There are probably multiple parsers out there for JavaScript or for TypeScript, right? So are you using something that somebody else wrote or did you actually have to write your own or modify one that was already out there?
 
Dan (36:00.847)
Thank you.
 
Josh (36:07.798)
We, it's one of the sillier things I've seen in open source. We called a TypeScript API to parse a code file or text. We get the TypeScript format AST out. We then have a recursive piece of logic that converts all those TypeScript nodes into the equivalent ESLint AST nodes. And then we pass back the ESLint AST nodes. Does anyone want to guess why we have to do that?
 
Dan (36:27.898)
Hmm.
 
Charles Max Wood (36:28.787)
Oh, cool.
 
Dan (36:34.58)
because their structure is slightly different.
 
Josh (36:38.994)
Yes. And then also, TypeScript APIs don't know or care about ESLint. So if you want to use type checking, you have to get the corresponding TypeScript node for the ESLint node and pass that TypeScript node to the TypeScript type checker API.
 
Dan (36:53.524)
But you do the type checking, doesn't TypeScript just, why do you need to assume some of the onus of the TypeScript work? Why do you need to do the type checking rather than have just TypeScript do the type checking?
 
Charles Max Wood (36:58.656)
Right?
 
Charles Max Wood (37:10.516)
Yeah, now we're into that they should be three different tools, right?
 
Josh (37:14.146)
Well, 15 different tools at the end of the day. Yeah, so by default, no type checking is done. Type checking is slow, no one likes slow. By default, we just parse and pass back the notes. It's also much easier, by the way, to just ask TypeScript to do all the fancy, schpancy parsing. Code can get complex, so it's nice having TypeScript do it for us most of the way. But later on, a rule might be given the TypeScript ESLint AST, which is like the ESLint AST but more, and then wants to know the type of a node.
 
And in order to know the type of a node, you then have to grab the corresponding TypeScript node and then pass that to the TypeScript type checker. So that's, that's why we generate both trees and keep actually both trees in the parsed outputs, even though most rules mostly just use the ESLint AST.
 
Dan (37:42.624)
Hmm.
 
Josh (38:01.399)
Ta-da.
 
Dan (38:01.768)
Interesting. And yeah, go for it Chuck.
 
Charles Max Wood (38:04.14)
So how much work are you doing on the parser then versus... I mean, you still have to parse the AST so that you can get the information you need from it to give people feedback, right? You violated this rule. So how much of the work is on the parser? How much of it's on understanding and reading the AST? And how much of the work is then on giving people feedback?
 
Josh (38:29.086)
I'd say because we're built as a set of ESLint extensions, plugins and rules and so on, it's actually not that much work for us to do most of that. ESLint manages the running the rule and having a VS code extension that reruns and so on. Unfortunately, because TypeScript only releases a new minor version every, let's say three or four months, we just have to update our tooling for new TypeScript versions every three or four months. Most of our work either goes into user education because for a while that was...
 
Charles Max Wood (38:42.909)
Oh right, that makes sense.
 
Josh (38:58.07)
not very invested in, in our section of the community, or in rule maintenance, writing new rules, fixing bugs and rules, discussing with people what should be a rule versus, and so on.
 
Dan (39:09.568)
How do you come up with new rules for TypeScript?
 
Josh (39:14.422)
We have a public issue tracker. I would encourage anyone who has an idea for, wow, I wish the linter would catch this too. Of course, first search for duplicates and other discussions, and then go on the issue tracker and perhaps file an issue. For the most part, we try not to get into stylistic battles. Like we won't enable, let's say a rule that bans enums. Like that comes up a lot because types of enums are this controversial feature and it's a whole thing. But we will try to figure out what are the rules that-
 
every code base would at the very least want to be able to configure and have. And then if that rule is something that you can make a standard suggestion on, let's say don't use var, that's pretty popular as a suggestion, then we could enable that rule in one of our preset recommended configs.
 
Dan (39:57.468)
Yeah, but that's really a JavaScript rule or ECMAScript rule rather than a typescript rule.
 
Josh (40:02.85)
Sure, yeah. So we have a rule. You can only contribute or suggest a rule for us if it either needs type information to work because we're the only standard winter plugin that's popular and has type information, or if it's specific to TypeScript. So like actually, yeah, the example I gave you right is like a little eh, because that's really an ESM rule. But there are some ESM rules that don't work well in TypeScript code because of bugs, so we do replace some of them with our own rules, and that I think is why.
 
Charles Max Wood (40:30.636)
So with the enum rule, would you write the rule and then just not turn it on by default? Like, would you build it?
 
Josh (40:36.726)
Um, we wouldn't build it, but we would encourage someone to use our, I think, well-documented tooling on top of ESLint's well-documented tooling to write their own darn plugin and enable it on their projects. And I was wrong by that. We don't, we create the ESLint no var rule, but we do have rules like, um, no, no var requires, which says don't, uh, don't require something using var what equals require parentheses. We would prefer like an ESM import.
 
Charles Max Wood (40:46.636)
Okay.
 
Dan (41:08.161)
Um, and what is your like release process? What's your versioning?
 
Josh (41:15.134)
We release canaries whenever there's a new commit, but for the most part people just use our Monday release of New version so we use pretty frequently we over the last few months Have been kind of reacting to bugs and feature requests from a new major version that we released which was v6 we generally save majors for Changes to our preset configs of which there are now I believe six popular ones
 
Recommended, strict, and stylistic. Yeah. I need to catch my breath for this discussion. There's a good reason, set of reasons, but it's a whole thing. So please give me a moment to compose myself before I tirade. But OK. So there's the recommended preset config. Every ESLint plugin, or almost every ESLint plugin, by convention exposes a preset list of rule, enables, disables settings, called recommended. Good.
 
Dan (41:45.284)
Wow, that's a lot!
 
Charles Max Wood (41:47.37)
Hehehe
 
Josh (42:12.978)
separately from recommended, have a superset that's recommended type checked. If you go through the extra effort of telling our parser about your type information, what your TS config looks like or where to find it, then we can enable more powerful but also more slow rules for you. So that's two preset configs. In v6, we split out the stylistic recommendations because, as we've discussed earlier, developers don't like being told stylistic conventions that aren't for them. But we do have our stylistic recommendations.
 
And some of them can be, I think, quite valuable for enforcing consistency. So that's four. Recommended, type checked. Stylistic, type checked. We also have a lot of really good rules. Yeah.
 
Dan (42:51.508)
There's stylistic type check? There are stylistic rules that require type information?
 
Josh (42:57.119)
Yes.
 
Dan (42:59.176)
That's interesting.
 
Josh (43:01.699)
I'm just querying on our site because I don't remember off the top far head. Oh yeah, prefer optional chain. Knowing whether something should be the question mark dot is in theory kind of a stylistic concern. It doesn't fix your bugs, but knowing whether it's safe to use an optional chain is a whole other thing. Also, prefer string dot starts with.
 
Dan (43:07.881)
Hmm.
 
Dan (43:20.336)
Like it's not undefined that you can't, you can't.
 
Okay, I understand what you're saying. The property might be undefined, but if the object itself is undefined, that's a problem.
 
Josh (43:33.502)
Yeah. And then what if it's a string versus an empty string instead of like null? Or what if it's type is string or null or undefined? And then what if someone changes the comparison and so on? It gets tricky.
 
You're starting, I see in your eyes, you're starting to understand how painful this is to try to make opinions or enforces on.
 
Dan (43:46.409)
Well, ca-
 
Charles Max Wood (43:49.941)
Ha ha.
 
Dan (43:52.676)
Well, well, look, to be, to be honest, the, the problem is not so much the, the quote unquote pain of adding all the types. It's the quote unquote pain of also supporting the world that doesn't have types. I mean, if you're looking at other programming languages that, uh, where typing is the thing that there is no untyped option. Then.
 
their linters are often more strict and they're not complaining about the fact that, you know, everything is kind of doubled because that's just the way it is.
 
Josh (44:31.518)
Yeah. And those languages don't have flavors. You know, there's just C sharp, which I will maintain is a beautiful language. Love C sharp. There's no, you know, C sharp, but the way Microsoft interprets it, or there's no, you know, ES next for C sharp is just the version you're running on.
 
Dan (44:46.044)
Yeah, but effectively TypeScript has, you know, like it or not, and whatever you said about Microsoft, it's effectively become the de facto standard for TypeJava.
 
Josh (44:58.294)
Yeah, which is a little painful to me. I love TypeScript. I think it's fantastic. I'm obviously a big advocate of it, but it's a risk, not a bad thing necessarily, just a risk for a community to settle on one JavaScript variant, or one JavaScript flavor. So I always try to make sure it's separate.
 
Dan (45:14.5)
I think Microsoft, is it Microsoft like submitting it as a standard or something?
 
Charles Max Wood (45:14.536)
Yeah, I'm also gonna...
 
Dan (45:23.368)
Hmm, interesting.
 
Charles Max Wood (45:23.572)
I also want to point out real quick, you said C sharp is a beautiful language. And we're talking about TypeScript and Anders Heilsberg is actually the brain behind both. So.
 
Dan (45:31.1)
Yeah.
 
Josh (45:32.68)
Yeah.
 
Yeah. And it's funny because a lot of syntax in JavaScript today and TypeScript and C sharp, they all learn from each other. Every language learns from each other, right? Like there's stuff in Ruby that informs JavaScript and vice versa.
 
Charles Max Wood (45:42.376)
Yeah, they all do. Yeah. Ruby is a beautiful language. Just saying. Right. Anyway.
 
Josh (45:50.452)
Sure.
 
Dan (45:53.148)
Every programming language is beautiful in its own way.
 
Steve (45:58.387)
Everything is beautiful in its own way.
 
Charles Max Wood (45:59.132)
I'm thinking the white space language or something.
 
Dan (46:03.948)
Oh yeah, whitespace. You know what? Well, whitespace is the only programming language you can write inside programs written in other programming languages.
 
Josh (46:12.702)
Yeah. I used to work at Codecademy and a couple of years we did language courses as April Fools jokes, not pranks. They were real courses. My first year we did it on LOL code, which is like a meme language. And then the second year we did it on emoji code and we actually exposed quite a few bugs in the platform having a language entirely based on emojis.
 
Charles Max Wood (46:34.86)
Nice. So I kind of want to move us along to if people want to use this, so I'm using this project, you know, or I'm writing my code in TypeScript and I'm like, oh yeah, you know, it'd be nice to lint my TypeScript code. How well do you play with some of the frameworks that either highly encourage or mandate to use TypeScript? Do you get into some of the sort of semantic or?
 
conventional ways of writing TypeScript there and make it all conform with the React way or the Angular way or the Vue way.
 
Josh (47:14.194)
I think we work pretty well with them. I've actually been off and on trying to work with some of the bigger reactor front end frameworks to get them to recommend using types could be recommended rather than having not that. For example, create next app doesn't do as much around us as I wish it would.
 
Dan (47:30.816)
Create Next app is kind of deprecated, I think.
 
Charles Max Wood (47:32.204)
Mm-hmm.
 
Josh (47:34.382)
Well, that explains that. Yeah, I love Next.js. It's so stable. I sure hope they don't change how we write pages.
 
Charles Max Wood (47:35.244)
Well, behind the times there, Josh.
 
Charles Max Wood (47:45.182)
hahahaha oh f-
 
Dan (47:45.572)
Ha ha!
 
Josh (47:47.644)
I'm a big Next.js user. I feel comfortable teasing them.
 
Dan (47:48.176)
Don't you know NexJS is the future of React? They even said so themselves.
 
Charles Max Wood (47:56.684)
Ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha
 
Josh (47:56.895)
I'll come back on and we'll have a full discussion about server components. It'll be great. But yeah.
 
Charles Max Wood (48:01.105)
Is it next JSConf coming up?
 
Dan (48:03.218)
We had one. We had Dan Abramov on the show a while back, a double header, like a two episode, it was such a long discussion. It came out as two episodes. I highly recommend it by the way. It was a really good discussion.
 
Josh (48:07.281)
Ah.
 
Josh (48:14.462)
Yeah, it was in the spring of this year, right? April, March, something like that. But yeah, we work well with other frameworks. Because we generally only have rules. Actually, we explicitly only have rules that are core to pretty much virtually all TypeScript users. We don't get into situations where we recommend something that's bad, let's say, for the specific framework. And actually, speaking of server components in React, there is one case where we're starting to get into a little bit of a, not conflict, but a...
 
Dan (48:18.388)
something like that.
 
Charles Max Wood (48:31.701)
Okay.
 
Josh (48:43.23)
you know, a mismatch, which is that some Next.js APIs require that you define your functions as asynchronous or returning a promise in the TypeScript types, even though the functions actually don't really need to be async. And we have a rule that says if a function is async, it better do something asynchronous, otherwise that's an unnecessary async.
 
Charles Max Wood (49:01.612)
Hmm, interesting.
 
Dan (49:02.1)
But it goes, it goes beyond that. I mean, if you have use client, a use server or use client at the top of. And next JS react file, it kind of changes the semantics of things that are allowed or not allowed in the file. It's even not just a TypeScript ESLint problem. It's an ESLint problem. I would say.
 
Josh (49:32.51)
It changes the runtime behavior and what you're allowed to do, which therefore changes what some lint rules might care about. For example, the React-specific lint rules. But it doesn't change how one might generate type information for a file. So I'm knocking on every single piece of wood near me in my room right now. It hasn't impacted us yet, and I hope it doesn't. But we'll see.
 
Charles Max Wood (49:54.796)
So going back to.
 
Dan (49:55.176)
But you said, oh, sorry, just that you made that quick note before that if you're creating, let's say, server functions, they have to be a sync or something like that, even though they are not actually, they're seemingly not actually used as a sync function or stuff like that.
 
Charles Max Wood (49:59.261)
Yeah, go.
 
Josh (50:22.874)
I don't remember exactly which parts of Next.js this applies to. I believe this is a Next.js specific thing. It's not a React specific thing. So I want to say it's, get server site props. Forgive me. I've been too deep into the Apollo, sorry, the Astro space lately. So I forget some of these things, but this is not a React thing.
 
Charles Max Wood (50:39.264)
Hehehehe
 
Dan (50:40.205)
I'll give a different example though. You've got server dollar both in solid and in quick. In solid functions wrapped inside server dollar have to be a sync. In quick they don't. You know if you're trying to create ESLint rules that work across all these frameworks you might actually need to have different rules for different frameworks.
 
Josh (51:07.534)
Sure. At that point, if there was a framework-specific best practice or even necessary practice, they can either put it into the TypeScript type definitions if that is, in fact, something that's type system enforceable, such as if a particular API needs to take a promise that returns, sorry, needs to take a function that returns promise, not function that returns anything else, then they can say that. And or they could create their own ESLint plugin, like ESLint plugin solid or ESLint plugin react. But for us, we just enforce things
 
common to all JavaScript. We don't care what the framework best practices are. If the framework is asking you to do something that's silly or unnecessary or just plain bug-ridden in a way that is obvious in the JavaScript syntax or TypeScript types, then we get into conflict. But these frameworks are written by teams that do a lot of research. So we have yet to see this actually be an issue for the most part.
 
Charles Max Wood (51:59.84)
So if I then get into something and let's say React wants me to write format things in a specific way, right? And maybe I'm coming from Angular where they, you know, the kind of the way people do things there are a little bit different, but they're all syntax, you know, your linter is going to be fine with it either way. But yeah, it's just not the way people write code in that particular community. Then those people would just...
 
have another plugin that goes on top of TypeScript.eslint that is the Angular TypeScript.eslint and says, hey, we format our classes or whatever this way, and we add our properties this way. Since it's all happy, valid, not bug causing TypeScript, then yeah, I can have my linter on top of yours that isn't going to collide or conflict.
 
Josh (52:57.834)
Yeah. Fun fact about Angular ESLint, by the way. That's the name of the project that's Angular ESLint. Yeah. And it's one of its core maintainers. If it's not one, I forget how many they have. James Henry is also a core maintainer and actually the creator of TypeSoup ESLint. So traditionally, we've worked pretty well with the Angular
 
Charles Max Wood (53:03.088)
Oh, there is one. Okay. It doesn't shock me.
 
Dan (53:16.832)
Well, Angular was one of the first frameworks to actually embrace TypeScript as I recall.
 
Josh (53:21.323)
Yeah.
 
Charles Max Wood (53:22.332)
Yep, they were trying to do their own script and then they, there were reasons, but they switched and it's been interesting to watch. So yeah, but they fully embraced TypeScript and I think it's worked well for people who have been writing it.
 
Dan (53:39.84)
So we kind of stopped you halfway. You mentioned that you've got six configurations, and we only gone through four. So we had the like, can you go back through the ones you already mentioned, and then proceed to the last two?
 
Josh (53:45.247)
Oh yeah.
 
Josh (53:57.142)
Yes, the last two are my favorites, the juiciest. We have recommended and stylistic, that's the X axis of two, and then we have the Y axis of, whether it's the regular one or the super fancy superset type checked one. We then also have a lot of rules that are really powerful, often but not always because of type information, but are a little too strict for everyone.
 
They're nice, I personally use them, but people who on board to us in the past have experienced pain from just 50 million of these rules complaining. So we have a... it's a legitimate user pain, you know?
 
Charles Max Wood (54:31.408)
No, this happens to everybody. They come in and they turn on the linter and they're like, oh man.
 
Dan (54:39.272)
Yeah, I love those builds that have like a million warning messages and everybody just think, you know, you ask them, one of the developers, oh, we just ignore these.
 
Josh (54:45.284)
Ugh.
 
Josh (54:51.55)
Yep. You're training developers to ignore the linter. What could possibly go wrong? So we split out the rules that are a little more nipicky or a little bit less easy to demonstrate immediate value from into configs, a regular version and a type check version called strict. So we have two config groups, each of which have a regular and a type check version. And an example of a strict rule is a weight variable, because it's not immediately obvious sometimes how to fix it. So it's great. We recommend it.
 
Charles Max Wood (54:51.819)
Yeah.
 
Dan (54:56.84)
Hahaha
 
Charles Max Wood (54:57.58)
Hehehe
 
Josh (55:21.13)
not everyone would want to use it to start.
 
Josh (55:27.undefined)
That's all.
 
Charles Max Wood (55:28.236)
Yep. Now it's pretty easy to get going with it, right? You just yarn install it and.
 
Josh (55:37.23)
Eh, give or take. It's straightforward. You tell your ESLint config that your parser is now our parser. Then you can also extend from our recommended rule set in addition to the core ESLint rule set or whatever else you were doing. And that's basically it for the regular ones. For type information, you should also say the parser options object has a project property saying either true for just find the closest to ES config type true.
 
Charles Max Wood (55:38.961)
No? Ha ha
 
Charles Max Wood (55:52.67)
Okay.
 
Josh (56:05.966)
configuration file for each file, or a specific string or array of strings. That's the path or globs. That gets a little more hairy sometimes. For most small to medium-sized projects, yeah, it's straightforward. It's fine. For bigger ones where performance of type checking becomes a real concern, then there are some things you might have to do. And we actually have a, I think, really exciting experimental flag about using more optimized TypeScript APIs called the Project Service that I'm hoping to land in core stable within the next year. But...
 
Yeah, for the most part, it's straightforward.
 
Dan (56:37.248)
So is building speed a real concern? We talked about the caching problems that arise with linting TypeScript.
 
Josh (56:48.318)
It is, yeah. In theory, your typed lint should only ever be slightly slower than your type check, your TSC run, because most of the work is running type information. ESLint itself is actually quite fast. That's one of the reasons why a Rust alternative to ESLint has yet to really get popular enough to overtake ESLint. It's not really an issue. But then type checking, especially if you misconfigure it or have some weird performance shenanigans with your types, which is possible annoyingly, then...
 
then there gets more pain there. But I'm hoping, like one of my big goals for joining the Type 2 BSLing crew is that I don't want there to be any major, you know, roadblocks or pain points that a lot of people hit. And this is the last of the really big ones that I wanna tackle while I'm here.
 
Dan (57:33.812)
The performance issue?
 
Josh (57:35.722)
Yeah, yeah, yeah. So for context, right now we use some TypeScript APIs that allow us to manually instantiate what's called a project. That's the TypeScript representation of one of your TS configs or projects in code. And because we do that manually, it's sometimes a little difficult to fine tune things for performance. For example, if you use TypeScript project references, then we have to do a lot of work and we don't actually fully support that.
 
TypeScript has an API called the Project Service, which takes on much more of the work for generating projects and is actually what editors like VS Code use. So if we were to switch to the Project Service or give users the option to, we in our experiments have seen that you can get up to significant performance improvements. I think it's like up to 50% faster or 30%, some large number. But it's a little buggy. So not ready, but very exciting.
 
Charles Max Wood (58:21.44)
Oh wow.
 
Dan (58:27.808)
So you're not thinking about rewriting everything in Rust or something.
 
Josh (58:33.382)
No. First of all, although I actually learned C++ back in college, I don't particularly want to work in that low level of a language, even though Rust is beautiful. I know we said all languages are beautiful, but Rust is beautiful. It's just not my core competency right now. Takes some time. But also, because the TypeScript type checker is not yet available at Rust speeds or lower optimized language speeds, it's only written in TypeScript right now.
 
And the closest project to recreate it in Rust, called STC, very, very exciting, very cool project, is nowhere near production ready on our timelines. So any, any linter written in Rust or Zig or Go or whatnot would have to either re-implement all of TypeScript, good luck with that, or suffer the performance penalty of calling to code that executes in JavaScript.
 
And that's why it hasn't happened yet.
 
Charles Max Wood (59:29.748)
Awesome. So is there anything else we should know about?
 
TypeScript ESLint.
 
Josh (59:38.606)
Whew. Well, I'd say for anyone who hasn't overhauled their ESLint config in the last year, go through our docs. I highly recommend it. There's a lot of good stuff in there. I also recommend there's a great repo called Awesome ESLint, dspec or slash Awesome ESLint, that has a giant list of really great ESLint plugins. One that I'd love to shout out is the deprecation plugin.
 
which lets you know if you call to some method or use something in code that's marked with the JS dog, that deprecated. I'd say ESLint or linting in general is not the only thing that one could do to make code good. I've been really into this tool lately called Knip that finds unused code in a way that would not really be doable in a linter. Very big fan of that.
 
Charles Max Wood (01:00:25.08)
Josh is frozen.
 
Dan (01:00:27.005)
Yeah.
 
Josh (01:00:28.071)
Oh no, I'm not frozen.
 
I swear.
 
Charles Max Wood (01:00:32.796)
Okay, we can hear you now.
 
Steve (01:00:33.023)
You were, you just had to sing the let it go song.
 
Josh (01:00:36.436)
Oh no. What did you hear from me?
 
Dan (01:00:40.552)
No, only for just three seconds or so. It wasn't.
 
Charles Max Wood (01:00:44.188)
Yeah. You told us about awesome ESLint and then you were making another point.
 
Josh (01:00:45.678)
Oh man.
 
Josh (01:00:51.31)
Oh, yeah. Separately, yeah, the deprecation plugin is great. There's also a really nice tool outside of ESLint called Knip, K-N-I-P, that I've been using recently that finds unused code dependencies and so on in a way that's actually not really doable in a linter. Yeah. It's shocking sometimes, the things you find with unused code detection. So I'd say take a look at your whole dev process and see linting, testing, type information, unused, et cetera. What parts of it haven't you looked at?
 
Charles Max Wood (01:00:52.699)
Deprecated, you talked about deprecated.
 
Charles Max Wood (01:01:06.368)
That'd be nice.
 
Steve (01:01:14.283)
So that.
 
Steve (01:01:21.175)
So that would be something like a post CSS for CSS, where you're going through and getting, or one of the things you can do where you can go and get rid of code that's not being used.
 
Josh (01:01:29.482)
Yeah, but it's really powerful. Like it'll find interfaces that are, let's say, exported from a file and never used, or dependencies that you declare in your package JSON and never use, or dependencies that you don't declare in your package JSON, but then do refer to. So that's exciting.
 
Dan (01:01:45.628)
Yeah, so I just found an article about it on Smashing Magazine. Knipp, an automated tool for finding unused files, exports, and dependencies.
 
Josh (01:01:55.69)
Yep, that's the one. Lastly, I don't know if this will bring up a whole sub-conversation. I'm sorry if so. But we, TypeScript, ESLint, are an independent open source project. We're not sponsored by any major company, primarily. We are a bunch of randos on the internet. We're also separate from ESLint. So if anyone wants to contribute to us, whether that is time or money, we really appreciate that.
 
Charles Max Wood (01:01:58.571)
Awesome.
 
Charles Max Wood (01:02:19.724)
Good deal. All right, well, I'm gonna push us to picks. Dan, do you wanna go first?
 
Josh (01:02:20.066)
That's all.
 
Dan (01:02:27.732)
I'll try. So this is not fun times in Israel, to say the least. But I'm intentionally going to mostly avoid this also, just mention something at the very end about it. But I'll try to actually talk about more fun things. So one thing I really wanted to shout out is this TypeScript Origins, the documentary.
 
video that recently came out on OfferZen channel. I've only watched it halfway, but it's really good. It's kind of reminiscent of the documentary about Svelte that came out and also about React. Those documentaries that came out some months ago. So this one is also really good. And I...
 
recommend watching it. Like I said, I only watched about half, but the half that I watched was really, really interesting. Some unexpected twists and turns along the way. So, you know, it turns out, at least the way that they put it, that TypeScript was kind of the thing, like the first major open source project that Microsoft ever did, which is really interesting. And they were really kind of, it was
 
one of the signals of the changing of the guards from Balmer to Satya Nadala that they could actually even do TypeScript. So it's a really interesting story. So that's one pick that I want to mention. Another one is on the Programmers are also Human channel. They recently released a really, really funny video.
 
Uh, these are the same guys that created the interview with a senior JavaScript developer, which was hilarious. So they now introduced an interview with a senior Rust developer in 2023, which is also absolutely hilarious. And I highly recommend watching it. It's so funny. I'm not going to try to repeat any of the jokes because I'm just going to ruin them. And, uh, and you know, just watch it and, uh, and it's great.
 
Charles Max Wood (01:04:41.568)
Ha ha ha!
 
Dan (01:04:47.032)
And I did say that I will mention something about Israel. So what I will mention is that President Zelensky of Ukraine actually came out with a video supporting Israel in its hour of need and also actual people in the Ukrainian army fighting in Ukraine.
 
also came out with support with the supportive videos for Israel and That's unfortunately a lot more support than the Israeli leadership has shown to you to Ukraine So it's kind of kind of really puts us to shame I want to say that I'm really grateful for the Ukrainian people for their support and I'm as Almost on every show calling for other, you know The people of the world to support the people of Ukraine in their hour of need
 
And those would be my picks for today.
 
Charles Max Wood (01:05:46.016)
Alright Steve, what are your picks?
 
Steve (01:05:51.043)
Well, let's see. First thing is I'm going to second a pic. A couple weeks ago, AJ had mentioned the movie Gran Turismo. That was really good. And so I took my son to see it and we loved it. Really good movie. Apparently based on a true story. A little reading about it. Short version is Nissan was looking for ways to get some drivers and they had a Gran Turismo simulation game, really involved simulation game, and they picked
 
Some of the fastest racers from the game took them to this academy, taught them how to really race actual cars and then took one and had them out driving and that's the main character. So.
 
Dan (01:06:29.936)
Isn't that kind of the script of the last Starfighter movie from the 80s?
 
Steve (01:06:34.043)
Yes, yes, exactly. Well, that one was based out on the arcade game, I guess. It was called The Last Starfighter. That was a great movie. I still remember that one. Anyway, yeah, and I'd forgotten about that movie. Anyway, and then after that, we liked it so much that we went back and watched Ford vs. Ferrari 2, which is another I thought was a very good movie with Christian Bale and Matt Damon.
 
Charles Max Wood (01:06:35.52)
Kind of.
 
Josh (01:06:36.755)
Also, Ender's Game?
 
Charles Max Wood (01:06:43.211)
Yeah.
 
Yep, I watched that with my kids.
 
Dan (01:06:56.425)
Mmm.
 
Charles Max Wood (01:06:56.78)
Well that's another great one.
 
Josh (01:06:57.698)
That's a good one.
 
Steve (01:07:03.423)
For sure, that was a great story. So anyway, good job, AJ. That was a good pick. And now for the highlight, the dad jokes of the week. So recently, I heard a story about a ship carrying blue paint that collided with a ship carrying red paint, and 50 sailors were marooned.
 
Steve (01:07:25.172)
All right.
 
Dan (01:07:25.949)
Okay, that's a good one.
 
Charles Max Wood (01:07:26.449)
That one was pretty close to funny.
 
Josh (01:07:28.91)
That's pretty good.
 
Steve (01:07:30.997)
Yes. In my spare time, which I have a lot, I'm writing a book about all the things I should be doing in my life. It's my Autubiography.
 
Steve (01:07:41.111)
All right. And then this one's sort of a tongue twister, so I have to say it slow. I asked my son the other day, I said, "'What do you call a bunch of indifferent pumpkins grown on a hill in Norway?' And he didn't know, so I said, "'A horde of bored fjord gourds.'"
 
Steve (01:07:59.783)
And he was floored by the way. So those are my picks.
 
Charles Max Wood (01:08:05.452)
All right, I'm gonna jump in with a handful of picks here. I usually do a board game pick. I'm not gonna do that this week, just because I've been traveling all week and I'm not thinking of one that I'm just like, oh, I should pick this one again. So let me kind of move into some of the other stuff. So I mentioned last week, I did the Rails World in Amsterdam and it was such a good trip.
 
A couple of things that I did that I'm going to shout out about. The first one is I went to the Anne Frank House. I hadn't been able to get into it before. It turns out if... Well, you have to reserve your spot. If you don't buy a ticket in advance, you can't go. I paid for a ticket. I found out when they open up the tickets, which is on Tuesdays, and I think it's like six weeks in advance.
 
Dan (01:08:45.16)
The line can be terrible there.
 
Charles Max Wood (01:09:02.676)
Literally Tuesday, six weeks in advance, I got on and made sure I had a ticket. And it's in the building where they hid, right? It's not where they were living, it's where they hid. And so you kind of go through and they explain the whole Nazi occupation and then you actually get to walk through the space that they hid in. And boy, if that doesn't make you really think about how lucky you are to be where you are, right? Anyway.
 
If you have a chance to go, it's pretty amazing.
 
Dan (01:09:35.86)
I'll interrupt you for a second because I cannot, I can't help myself. Some of the stories, unfortunately, it's incredibly sad and quite unsettling. Some of the stories coming out of what happened in Southern Israel are reminiscent of that of people hiding in their houses, trying to quiet their babies. While.
 
Charles Max Wood (01:09:40.934)
Okay.
 
Charles Max Wood (01:09:54.396)
Mm-hmm. Yes.
 
Dan (01:10:02.364)
while terrorists were roaming the street and literally hunting for people. And some people survived by managing to hide and a lot, and many didn't. So yeah, that story is very reminiscent of what just happened in Israel, which is shocking.
 
Charles Max Wood (01:10:20.36)
Yep, absolutely. Some of the videos that are coming out of Israel are just, they're really hard to watch. If you're sensitive to any of that, don't watch them. I kind of wanted to get a feel for what was going on. So anyway, it's really terrible what was going on down there. Yeah, they were going house to house. Anyway.
 
I don't want to go too deep into it because yeah, I don't want to take this in a dark direction but you know, be aware of the kinds of things that are going on there for sure.
 
Charles Max Wood (01:10:58.24)
But yeah, so also in Amsterdam, one of the other things I did is I went out to another city, it's about a half hour away from Amsterdam called Leiden. And Leiden is a city, they had a little bit more enlightenment thinkers back in the 1600s. And that's why the American pilgrims went there before they came back and went back to England to get on the Mayflower.
 
The only reason they went back to England to get on the Mayflower at all was that the king granted them a charter and basically gave them free passage because they were criminals for their wrong thing in England. So they had left England. That's why they left. But he granted them the charter to go settle in the New World so they could travel through England and were granted safe passage to get on the ships.
 
and then one of the ships had trouble and had to turn around. But anyway, I went out there and just kind of wandered through the city. Now there's not a whole lot there that was there in the 1600s. It's a fairly modern city. There was or there is a museum for the American pilgrims there. It's really just one room and it has time period artifacts. But it was really...
 
interesting just to kind of hear him talking about, you know, some of the things that I'd learned about in school. And I think in some cases, I knew more about some parts of the story than they did. But it was really, really interesting to kind of get a perspective, you know, in Leiden, you know, which is where they were living until they got that charter and went back through England to get on the Mayflower. And incidentally, I have three ancestors that came over on the Mayflower. So it was kind of...
 
Dan (01:12:29.216)
Thanks for watching!
 
Dan (01:12:47.785)
Wow! Your royalty, Chuck!
 
Josh (01:12:48.983)
Wow.
 
Charles Max Wood (01:12:51.548)
I don't know about that. They were poor people and half of them died when they got here. But, you know, I just, you know, kind of what we're seeing in Ukraine and Israel and, you know, it's this same desire to just be free and live the way that we, you know, desire to live and have those opportunities. Anyway, it's really kind of been hitting home for me lately, you know, how fortunate I am because some people were willing to sacrifice, you know, to
 
to take the chance to take two months to come across the ocean. And then even then it was, you know, it was in Massachusetts in the winter, you know, the only real shelter they had was the boat that they had come over on. And you know, some of it's, you know, miraculous the way that it all worked out. But anyway, so I kind of had those two things go on. And then
 
more on the code front. I was there for Railsworld, as I mentioned. Really had a good time looking into Hotwire and some of the things that they're doing with Rails to enable some of this stuff with stimulus. I'm getting a little bit more into that. I'd really love to do an episode one of these days and just talk about Hotwire and stimulus and the way that Rails handles some of the front-end assets that we don't really talk about.
 
in some of the other circles that we move in. And then somebody mentioned the React documentary. They did a Rails documentary, the same people that did the React documentary, and they released it at Railsworld. Yeah. And the...
 
Dan (01:14:25.892)
Oh yeah? Cool, I'll watch it. That's really interesting.
 
Josh (01:14:29.538)
Hmm, I didn't know that. Thank you.
 
Steve (01:14:32.111)
I believe there's one for view as well that's been around for a couple of years.
 
Charles Max Wood (01:14:36.336)
It wouldn't surprise me. I don't know if they're all done by the same people. It looked like this felt one was done by other folks, but because I looked that one up too. But anyway, they released it because it was the 20th anniversary of rails coming out. So anyway, fun stuff. Nope. DHH is actually like six months older than I am. So go figure. Anyway, so those are my picks. Sorry, I went a little bit.
 
Dan (01:14:53.569)
So DHH is not a kid anymore.
 
Charles Max Wood (01:15:06.24)
dark on one of them, but anyway, Josh, what are your picks?
 
Josh (01:15:10.734)
Oh boy, I've been taking notes on subjects. I wasn't expecting to give a movie recommendation, but one of my favorite movies that I was reminded of recently was, is Drive with Ryan Gosling. It was marketed as like this action thriller thing, but it's really more of like a psychological drama suspense film. And it's this beautiful contemplation on, you know, the beauty of humanity and human nature and being kind versus evil to each other. Also Ryan Gosling kills a guy in an elevator. So.
 
Dan (01:15:22.933)
Hmm.
 
Josh (01:15:39.8)
So beautiful, beautiful movie, great soundtrack.
 
Uh, yeah. Um, I was, I was recently at three conferences in order, um, JSDIE, which I believe is soon to be renamed to JSConfIE, uh, React Live in Amsterdam just before you were there and RevoJS in Timisoara, Romania. Um, they were all great. I believe the JSDEIE videos are up on YouTube now. Um, I think.
 
Charles Max Wood (01:15:44.693)
Nice.
 
Josh (01:16:07.55)
What's freshest in my mind is the Timișoara trip. We also went on this whole full day hangout excursion into Romanian village where we had this platter of traditional foods and soica and raki and all this amazing stuff. But we wanted this horse drawn carriage through the city or pardon me, the village. And it was an amazing time and highly recommend. It's only their second conference, but they organized it, the Rio JST incredibly well.
 
Dan (01:16:32.236)
Romania is indeed a lovely country. You do need to take into account that it's pretty huge. So you know getting around, plan on driving quite a bit. Not as big as the States obviously but it's pretty big.
 
Josh (01:16:46.014)
Yeah, they were saying that they were taking, you know, multiple hour or multiple like flights to get from say East Romania To where we were the west would have been 15 hour driving for them But it also served to remind me. Sorry to again go a little darker that you know This this is like many in the region of post-soviet country and many of the people there remember the soviet union or having relatives or friends disappeared so I don't
 
Dan (01:17:10.772)
They had Ceaușescu who was a pretty horrific despot, rolling there for many years.
 
Steve (01:17:14.805)
is awful.
 
Josh (01:17:16.906)
Yeah. I don't have anything salient to say on the matter, as I'm not an expert and I don't know what I could say, but I will echo what's been said so far about freedom and the ability to live.
 
Charles Max Wood (01:17:27.628)
All right, well, thanks for coming, Josh. This was a lot of fun. If people wanna connect with you online, what are the best places to find you?
 
Josh (01:17:39.222)
They could not do that. But otherwise, my username everywhere is Joshua K. Goldberg. K as in kite or Kevin, my middle name. I would encourage anyone to reach out and chat with me. I'm always happy to talk open source or TypeScript or whatnot. And that's Joshua K. Goldberg. It's on my website.com, Twitch, Twitter, YouTube. My Mastodon server is Faustodon, Blue Sky. Oh, yeah. I should mention, I stream code twice a week on Twitch when I'm not traveling for conferences.
 
Charles Max Wood (01:17:41.292)
Ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha ha
 
Dan (01:17:59.644)
Oh, you do stuff on Twitch?
 
Josh (01:18:07.986)
So my first stream in a little bit will be tomorrow at time of recording.
 
Dan (01:18:11.4)
So you stream live coding sessions?
 
Josh (01:18:14.666)
Yeah, coding is one of the things I do. It's open source in general, and honestly, a lot of it ends up being going through issues and pull requests.
 
Dan (01:18:22.896)
Something I can never figure out how a person does. I mean, I would feel so, I'm trying to find the phrasing, self-conscious, I guess, trying to, you know, streaming myself as I'm coding. One of my issues even doing pair programming is how self-conscious I get when somebody looks over my shoulder while I code. So I'm struggling with the concept.
 
Steve (01:18:32.107)
Yes.
 
Steve (01:18:49.075)
Yeah, you see how much time developers spend googling things they basically things they forgot how to do.
 
Dan (01:18:53.188)
I don't care about that. It's just the, I don't know. It's just, like for me, coding is kind of a private thing. I guess.
 
Charles Max Wood (01:18:53.708)
Mm-hmm.
 
Josh (01:19:03.246)
Hmm. I started coding in part as a private thing in the same way that I play video games privately. I don't like multiplayer. I'm there to enjoy myself, to build something, to really think and do it right. But I will say, many different people do or don't get into live streaming or pairing. It's not something everyone has to do. One of the ways that people do to get into it that was effective for me, your mileage may vary, was I started trying to intentionally view it as a way to get feedback. That I've...
 
Charles Max Wood (01:19:13.2)
Mm-hmm.
 
Josh (01:19:29.458)
not just very self-conscious and nervous, but also very neurotic that, oh my gosh, I must be doing it wrong. Everyone else knows things better. So I started pairing at work, even doing Bob sessions with the explicit intention of everyone yell at me so I can do better. And then I took that mentality to Twitch. And now it's also beneficial because a lot of people don't know what it's like to be an open source and don't understand why their issue with no reproduction and swear words, it's not going over well. So between those two things, it's, it's very useful for me, I think to, to live.
 
Charles Max Wood (01:19:46.88)
Ha ha.
 
Steve (01:19:53.332)
Hahaha.
 
Charles Max Wood (01:19:59.756)
All right, well, we'll go ahead and wrap it up here. Thanks for coming, Josh. Till next time, Max out.
 
Steve (01:20:06.943)
Adios.
 
Josh (01:20:07.97)
Thanks for having me.
 
Dan (01:20:10.656)
Just noticed.
 
Album Art
TypeScript, ESLint, and TypeScript ESLint with Josh Goldberg - JSJ 605
0:00
1:17:27
Playback Speed: