Video Summary and Transcription
This Talk explores the concept of types and their significance in software development, particularly in relation to TypeScript. It discusses the limitations and advantages of TypeScript compared to other tools like Flow and Ezno. The Talk emphasizes the role of types in bridging system boundaries and improving code quality. It also highlights the importance of type-checked linting and the future of ESLint. Additionally, the Talk mentions the benefits of faster and easier linting with projects like Biome and OXC, and recommends books for further learning.
1. Introduction to Types and TypeScript
I'm Josh. I'm really excited to talk to you today about Types beyond TypeScript. We're going to talk about four sections. What are types? What is this whole thing? Just in case you haven't played with TypeScript or Flow yet. Second, I want to quickly cover what types aren't. I also really want to talk about the stuff types are surprisingly good at. First, what can inform types? Like how you can set up your code to be well-typed. And then lastly, what types can inform? How having well-typed code can help tools run better on your code.
Hey, everyone! Oh, sweet Jesus. That's not good. I'm Josh. I'm really excited to talk to you today about Types beyond TypeScript. Yes. As Phil said, I do open source. Feel free to talk to me after this whole thing about that. It's a wonderful world. The ecosystem is always getting better. I work on projects. Who here uses TypeScript ESLint? Yes. Who here uses ESLint in general? Yes. Who here has sworn at ESLint or TypeScript ESLint? Yes. Who here still uses Mocha? Okay. Cool. I'm not talking about Mocha today. I'm talking about Type stuff. We're going to talk about four sections. What are types? What is this whole thing? Just in case you haven't played with TypeScript or Flow yet. Second, I want to quickly cover what types aren't. Whenever there's a new tool, as you may have seen in other recent developments in life, people get really excited and they use it for things that may or may not be good fits. And they can sometimes give the tool a bad name. I also really want to talk about the stuff types are surprisingly good at. First, what can inform types? Like how you can set up your code to be well-typed. And then lastly, what types can inform? How having well-typed code can help tools run better on your code. Really cool stuff. Are we ready for all that? Yes! Friday late afternoon at a conference.
2. Types and TypeScript in JavaScript
What are types? In order to answer that question, we have to ask, what is TypeScript? JavaScript is a syntax along with a vague specification on how to execute this syntax. The problem with this, though, is that there's no built-in way in JavaScript to declare the intent behind those values. Which is why we have TypeScript. TypeScript adds in a syntax on top of JavaScript. It's a superset, meaning it's all of JavaScript plus this new stuff, and that syntax allows us to say explicitly not just what the values are, but the intent behind those values. It's so useful that it begs the question, why don't we have other TypeScripts? There are three examples of tools that are in the same space as TypeScript but aren't as popular as it, and I want to quickly go over. First, just curious, who here used Flow at any point in time? Flow is a lot like TypeScript. It's from Facebook, but it's actually gone a different direction from TypeScript. It's still under active development. But instead of getting a lot of usage and going worldwide and making it so everyone should ever, who has ever wanted to use types could use it, Flow is a little more targeted.
What are types? In order to answer that question, we have to ask, what is TypeScript? In order to answer that question, we have to ask, what is JavaScript? What is JavaScript? At its core, JavaScript is this. JavaScript is a syntax along with a vague specification on how to execute this syntax. This is lovely. Look at this. We have a let thingy. We didn't used to have let. Used to have var. We have the ability to assign a variable to different values. The problem with this, though, is that there's no built-in way in JavaScript to declare the intent behind those values. The intent behind those values. There's no little thing you can put there to say this is only ever going to be, say, a string. And that's problematic because code gets really hard to work with at scale. Once you pass five developers, 50 developers, 500 developers, it gets really hard to manage that stuff. Which is why we have TypeScript.
TypeScript adds in a syntax on top of JavaScript. It's a superset, meaning it's all of JavaScript plus this new stuff, and that syntax allows us to say explicitly not just what the values are, but the intent behind those values. In this case, string. Now, because we have the TypeScript syntax, we can do things like the TypeScript type checker. Fun fact, written in TypeScript, and that's a CLI or API you can call to get little complaints saying, hey, you said this was going to be a string, but you gave it a number, you silly goose. That's not allowed. You can run the type checker through the language services for TypeScript, such as VS code, great editors, and those will give you the same complaints but in little red squiggly line form, type number not assignable to string. And that's really useful. It's so useful that it begs the question, why don't we have other TypeScripts? Why is TypeScript the only tool that seems to be in popular usage today for enforcing types in JavaScript code? Not that I said popular. There are other tools, but TypeScript has the mind share. Now there are three examples of tools that are in the same space as TypeScript but aren't as popular as it, and I want to quickly go over. First, just curious, who here used Flow at any point in time? A good chunk of us. Flow is a lot like TypeScript. It's from Facebook, but it's actually gone a different direction from TypeScript. It's still under active development. But instead of getting a lot of usage and going worldwide and making it so everyone should ever, who has ever wanted to use types could use it, Flow is a little more targeted.
3. Using TypeScript for Types
It's more for the Facebook style of use cases. TypeScript is written in TypeScript. It executes at JavaScript speeds. Ezno is an ongoing project attempting to rewrite a version of a language similar to TypeScript in Rust, but it's taking a while. We're kind of stuck with TypeScript right now, for better or for worse. This talk is about types. TypeScript just so happens to be the implementation detail of how we're writing and using them.
It's more for the Facebook style of use cases. It's diverged a bit which means it's dropped off in popularity compared to TypeScript. Now I mentioned that TypeScript is written in TypeScript. That means it executes at JavaScript speeds. It would sure be nice if we could execute at Rust speeds, at native code speeds, which is what the STC project was, but that project was abandoned because it turns out it's really hard to reimplement TypeScript in a new language. Ezno is an ongoing project attempting to rewrite a version of a language similar to TypeScript in Rust, but it's taking a while. So between Flow being all hipster, STC being abandoned, and Flow, pardon me, Ezno being in progress, we're kind of stuck with TypeScript right now, for better or for worse. Which means this talk is really just types. I'm talking to you about types, and it's a coincidence that I happen to be using TypeScript for that. But I really want to hone in on that. This talk is about types. TypeScript just so happens to be the implementation detail of how we're writing and using them.
4. Types and TypeScript: Bridging System Boundaries
Types and TypeScript are like information glue that merges different system boundaries or parts of your app. TypeScript helps bridge the gap between components by providing autocomplete and type definitions. Well-typed systems can be better understood. Function components in TypeScript are much easier to statically type compared to class components. TypeScript offers powerful features like generics, mapped types, conditional logic, extreme inference, and the ability to implement binary arithmetic in the type system. But remember, don't use TypeScript for everything!
Okay! New talk? Types? Yes. All right. All right. Let's think about types and TypeScripts. First of all, why do we like them? I like to think of them as an information glue that helps merge together or a bridge that helps bridge together different system boundaries or parts of your app. Suppose you have a new component. You've got that blinking cursor. What the hell are you supposed to do with this thing? Read the source? No, you would typically use the TypeScript autocomplete or the type definitions, the little drop-downs in your editor, to figure out, ah, someone wrote that there's some props for this component. That's really useful. And then if you get it wrong, TypeScript helps, it informs you, hey, you're trying to bridge that gap, but it's a pedestrian-only road and you're riding a bike. That's not allowed. So I want to really emphasize for that, the better typed your system is, the better your tooling can help you use it. Well-typed systems can be understood better.
Back in the day, does anyone remember writing class components in React? That was big for a while. A lot of us. This is how you used to write things. This is a lot of code. Classes are also actually really hard to statically type because a lot of the time methods other than the constructor might modify your state and then you have this weird case where other methods don't know. It's a nightmare. Even the code, it's, oh, my God, look at this! But now we have function components which are much easier to statically type. There's a reason why solid.js hasn't gone back to class components. And once you start writing things in TypeScript, you get this beautiful generic thing. You realise, oh, my gosh, TypeScript is actually really powerful. There's a lot of cool stuff you can do in the type system. You can do generics that reference other generics or specifically type parameters. You can have mapped types which map from one type to another. You can have conditional logic in the Turing complete type system. You can have extreme inference in your logic. You can implement binary arithmetic in the type system. You can use TypeScript for everything! Please don't do that.
5. TypeScript: The Type Cycle and Runtime Existence
TypeScript type cycle: peak of inflated types, disillusionment, and plateau of type productivity. TypeScript does not cure convoluted code or fix app architecture. Prefer simpler code resulting in simpler types. TypeScript does not exist at runtime. Proposal to add types to JavaScript as comments.
Do not go down that path. I understand yesterday there was a mention of the Gartner hype cycle. I like to refer to the TypeScript type cycle. Every developer who goes deep into TypeScript goes through this. You go through this peak of inflated types where you realise, oh, my gosh, the type system has logic, I can do everything in it. And then you overuse that and your team-mates have no idea what the heck your code is doing. So you then get disillusioned, and you then realise you don't know what the heck your code is doing in the type system. So you stop doing that, hopefully.
And then once you figure out the plateau of type productivity, when you're using TypeScript just the way it's meant to be used, and not overusing it, that's when you're most efficient. That's a good place to be. So that brings us to the second of four cases, what types aren't, or what TypeScript isn't in this case. TypeScript does not cure your convoluted code. TypeScript does not fix your app architecture. If you're writing incomprehensible, unreadable garbage, TypeScript can only band-aid on top of it. If you have complex ideas, the types describing those ideas will then likely have to be complex. So it's good to prefer simpler code resulting in simpler types. Pro-tip!
Also TypeScript does not exist at runtime. TypeScript is not a runtime helper. Types do not exist. When they get transpiled from TypeScript to JavaScript, your code areas just lose all those type annotations. Something like this does not work because interface some shape does not exist at runtime. The compiled JavaScript just doesn't have it, so you're referencing something that doesn't exist. Don't do that. No types for you. I do want to mention there is actually a proposal to add, quote, types to JavaScript, but it's just a new syntax for them. It's a space to put comments describing the types. Though this is a very exciting proposal, it's just comments. It doesn't actually capture all of what TypeScript is, so for a while, you would still need TypeScript as they iterate on it, and it's years away from early testing. Years and years.
6. The Zen of Types and Schema Validation
Adding types to JavaScript is controversial. Types should describe values. Schema validation libraries like Zod provide TypeScript parity and inference. Use Zod for data with shared, validated shapes.
Years and years. It turns out adding types to JavaScript is a somewhat controversial proposal, so it's going to be locked in committee for a long time. Oh, well. The reason why I'm really excited to talk to you about not using types for certain things is because types are not the root source of everything. Oftentimes, in your code, it's best that your types are just a description of or a by-product from your values. You write your code, and then the types describe how that code is meant to be. So no runtime types, I'm going to instead dive into the zen of types here. How do we go from really nicely described code, or really clear values, to really nice, clear, well-described types? In other words, how do we inform our types nicely?
The first thing I want to show is schema validation libraries, part three of four. Well-defined schema validation libraries, out of curiosity, who here has used one like YUP or Zod or ArcType? All great options. A lot of but not all of the room. Let's talk about this. Back in the day, we had this old thing in React called PropTypes used to be built into React and separated out. That was a very early way to describe a schema to validate and describe the props, the stuff that went into your components. Which is awesome. It was kind of straightforward, like, this code is pretty readable. It's understandable, I get what it's doing, but it wasn't fully TypeScript feature-complete, it didn't map to all the features one might want in the type system, and, as a result, the TypeScript inference story was never really fleshed out. You ended up with a lot of companies that would just write everything twice. We don't like that.
So instead, now, we have, well, often times, a new round of schema validation libraries like the ever-popular Zod. This is pretty similar-looking code, but the interesting thing is we have a separate schema, box schema, and then a built-in Zod helper called infer that takes in the box schema's type, the type of, and gives back an interface or a type. In addition to being straightforward usage and understandable syntax, we also get TypeScript parity and we get TypeScript inference. So that's really nice. Now, I'm not saying you should use Zod schemas for all your component prop types. If you're not validating your props, there's no need for that. But if you are using data, shared, usable, validated shapes, this is quite nice. So this is just an example of how Zod might look in a more complex app. Zod supports unions, which are types that represent values that can be one or more possible things, represents objects, optionals, all sorts of great stuff. One example of how you might use it would be if you have some unknown data and you want to render in a component, well, you could try parsing or safe parsing it with Zod, and if that's succeeded, you render the component box, or if not, you render some error. Notice how I'm not really doing a lot in TypeScript here. I'm describing the Z.infer, I'm describing what the props are, but my values are describing the logic, the flow, the if not parsed.success then do this thing, from values come types.
7. Shared Schemas and Code Generation
Shared reusable schemas improve type safety, autocompletions, and security. TRPC is a recommended approach for type-safe server-client interaction. GraphQL and open API (Swagger) are alternative approaches. Well-typed code can generate SDKs in different languages.
And what is also really interesting is once you have these shared reusable schemas, you can share between client and server. You can have the schema in the bundle on the client that describes the type you would send to a network request, and then you could also have the schema used in your code on the server to validate that the network request was sent to you successfully. That means you have better type safety, autocompletions, you have better security because I don't know how many of you have had to manually validate that request params are valid because you had a hacker one report, about a 500, but it is a nightmare, this is a much better way. And by doing so, you get this kind of symmetrical beauty between your client and server where you have the shared schema that helps both of them.
So there are actually quite a few different ways to do what I just described. The closest to what you just saw that I really recommend trying out first is called TRPC. Type safe what is it? What does RPC stand for? Thanks! I didn't hear anything! On your server, you can define your Zod schema and then a query thing, if someone gives you options with an input, you return a string. Notice the as constant there, that tells TypeScript to use that literal string type which you will see in the next slide. Once you have that on your server, you can also have it linked with the client. There is a little bit of skeleton backbone code here, but notice the last few lines on the right, await TRPC.greeting.query, name Attila, and the type of that variable is HiAttila, who by the way was the photo you saw earlier of the guy with the serious face.
Another interesting approach is GraphQL which is nowadays a little older but still good in large use cases. There are different ways to do it. One would be having a GQL or GraphQL file describing the GraphQL syntax for a type, and then some queries somewhere, maybe in a query file. I think I used the wrong extension on this slide. You can auto-generate types from those, from your schema and your queries. It is really useful. The last one of the three is open API aka Swagger. I have yet to determine which term is still in use in which context, but you can define a schema file, say in YAML, and auto-generate your code from that schema file. This is a small example. I've seen very big complex, in a good way, lots of features, SDKs generated from schema files. Alternately, you can go the other way. You can use well-typed code to be statically analysed by Codegen to create your schema file directly from your code. From your server, say, which means you can generate SDKs in different languages from your server. How ridiculous is this? We started off with a TypeScript server and now we are auto-generating SDKs in Python and Rust based off of that. Who here writes the SDK manually at a company that has multiple languages of SDKs? Oh, four of our hands. I expected it to be more. Clearly, you're all using open API. This is great. The better typed your system, the better your tooling can help it. The better typed your system, the better your tooling can analyse it.
8. Type-Checked Linting
Type-checked linting is a powerful tool for improving code quality. Linting, type-checking, and formatters are three forms of static analysis. Linters can teach new syntax and provide language-specific insights. Type-aware lint rules leverage the power of TypeScript to enforce best practices and optimize code execution.
What types can inform once they are well typed, well described is our last section, and I'm most excited about this one because I'm going to talk about what I work on day to day, type-checked linting!
Who here uses type-checked or type-aware linting? Wow! Actually, a good number. Thank you. That is awesome.
First of all, you should probably lint your TypeScript code. I can't say for sure, maybe you're not a lint-happy person, but if types are justified at your scale of application, linting is probably too. There are three forms of static analysis. Linting does not mean type-checking. There are formatters, like prettier, which just format your code, they don't change logic. That means they are in a good way dumb, very quick. Then there are type-checkers which are very powerful but slower, aka TypeScript. And then there are linters, like ESlint.
Now, linters are great. As an example, they can teach you new syntax. There's a built-in ESlint rule, logical assignment operators which would look at this code and say, fun fact, there is a new JavaScript feature that can write slightly cleaner code for you. Look at that. How nice. We learned something. You seem smart. And they can also teach language or framework or library-specific things. TypeScript ESlint would let you know, wait a second, that name, hi, Daria, there's actually a nice as-const feature you can use to do that same thing. Awesome. But that's just looking at the raw syntax. And once we have types, once we have an awareness of not just the one file we are looking at, but the entire project, we can write much more powerful lint rules. We can make this almost new classification of lint rules, like type-aware or type-check lint rules that tap into the power of TypeScript.
For example, you could look at this code, and because you have a type system behind you, you could say I know for a fact console.log is supposed to return void, nothing, not a thing to be used, which means the TypeScript ESlint await-venable rule could say you awaited a non-promise or by the spec non-venable value, something without a ven, that's unnecessary, that just wastes a tick in your program execution, so we could suggest you remove that.
Now, that example is not very exciting. I realize none of you have written await console.log, so let's look at something more exciting, some React code that I'm not going to give you enough time to read, but I will tell you that this has an onclick that's a function, and somewhere inside a handler that's supposed to set a running state to true, we await onclick. After that, we set running false. With the same lint rule, we could say hang on a second, onclick returns void, not promise, so the lint rule would tell us for this one I don't think you need to do that. So we could remove the onclick, or we could change the onclick to return promise void.
9. Type-Checked Linting Recap
If our code is supposed to return a promise, we can remove unnecessary code with linting. Types are information glue that help define system boundaries. TypeScript is not a runtime thing, it only exists during development. Well-defined schemas and type linting are recommended. TypeScript is supported by popular frameworks and ESLint has released a beta of types in ESLint V8 with great features.
If our code is supposed to return a promise, great, that works, but what if we never actually used that async behaviour? What if the await was supposed to be removed, because then if the await was supposed to be removed, we could see that we have two React set states, equivalents, those run synchronously, so we can remove them. Since we can remove them, the whole onclick and disable function is unnecessary, so we can remove that, which means the button disabled equals running, button disabled equals false, which means we can just say button, we don't need disabled, which means we've removed a third of our code with linting! Yes! Woo! Hell, yeah! Thanks for the lighting! Amazing. I highly recommend, I will show resources and references after this, use type-checked linting for a better informed, more powerful set of lint rules. It's a good time. So I'm almost out of time, I will just recap, I will go quick, these are photo capable slides if you want. First of all, what are types? Types are information glue, they help define system or component or area boundaries. They're great. Type script type cycle, please try to control yourself when you're first getting into it and learning all the advanced stuff. Type script isn't a runtime thing, it only exists during development. Values two types. The Zen area. Well-defined schemas are useful. Types can inform tooling but I recommend trying out type linting at the very least. If you want to get started, all the frameworks used in the framework authors and the first two rows support type script by default. We have great docs and ESLint and we just released a beta of types in ESLint V8 which has all sorts of great features, it is ESLint V9 support, which I know everyone is really annoyed at us not having yet, sorry, and it has a new way to configure type linting which is 10 to 20 per cent faster, significantly easier to configure and more fully featured. So that's all I have. Thank you very much, everyone.
10. Types versus Interfaces and TypeScript Versions
Types versus interfaces in TypeScript. Most of the time it does not matter which one you use. Personally, I prefer interfaces whenever possible. TypeScript 6.0 and 5.5 have exciting features. The new 'is assignable to' API will make writing powerful lint rules easier. Deprecating old syntax is also happening gradually.
The top question that has come in has been voted by many people. I'm sure you have been asked it before. Do you have an opinion? Types versus interfaces. Types versus interfaces. Oh, my gosh, what a question! It wasn't you, Attila? Most of the time it does not matter whether you use types or interfaces, the two are almost equivalent in TypeScript. They're both things that can define an object shape. I personally recommend just use the TypeScript ESLint rule that consists in type definitions that has you choose one or the other. Personally I prefer interfaces whenever possible because that's semantically what you're trying to convey. Type is kind of a coincidental copy and paste in terms of the TypeScript semantics. But if you're the type of person who is like I just use type for everything, jolly, good for you. That's fine too. There are some things you can only do with interfaces and some things you can only do with types which is really annoying. Should there be one unified thing? It's just how the language evolved over time. We can't change it.
I say we can't change it, but my next question is whether you have any insight into the future, any ideas on what might be coming in TypeScript 6. You know, every once in a while I have a conversation with someone who seems to think I'm on the TypeScript team. So just to be safe, I'm not on the TypeScript team. I have contributed in the past as an external person, but it's been a while. TypeScript 6.0 is going to have some awesome stuff. But even before then TypeScript 5.5 is about to go stable. You have the release candidate and beta out. And oh my gosh, 5.5 has these awesome features where type predicates can be inferred from function bodies. If you don't know what that is, that's awesome, just go read the release notes. They're fantastic. If you do know what that is, you know how awesome that is. Is there anything you'd want to see in TypeScript 6.0 or 5.6 or whatever? There's a new API that's recently been made available called is assignable to. That's going to make it a lot easier to write really powerful typed lint rules that I'm really excited about. Also they're deprecating a bunch of old syntax very slowly over time which is also very exciting. That's awesome, yeah. Yes, good.
11. TypeScript Limitations and Future of ESLint
TypeScript's limitations are both broad and specific. TypeScript itself does not recommend a specific approach, be it classes or functional programming. However, there are valid use cases for classes, such as small data packages or extending the error class. The future of ESLint compared to new Rust-based tools like OXC, Biome, and Dinolint is exciting. Currently, TypeScript ESLint is the leading linter with typed linting, but the landscape may change in the future.
I like slow deprecations. Very, very, overly slow. Overly slow. That's not a question. I feel like you covered a bit of this, but if there's anything you want to go deeper into, what are TypeScript's limitations? It's hard to answer that because there are broad answers that I already gave and then there are specific answers. So I'll answer that in person if you're interested.
Okay. There's Q&A in the booths over at the back there. Come talk to me. I'm very friendly. Okay. In that case, how do you feel about classes in TypeScript and or JavaScript? We're using, I guess, class syntax. Is that something you recommend or? TypeScript itself does not recommend either class approach or functional approach. It doesn't recommend OOP versus FP versus whatever. TypeScript just describes your code. Classes the way folks have traditionally interpreted solid principles and object-oriented programming actually really violate solid and OOP. So I'd say the way that you're writing classes in Java is probably awful. Only relatively newer Java practices have made me not unhappy. There are a lot of valid use cases for classes.
For example, small data packages that have a bunch of private helpers or extending the error class. So there are uses for classes. I personally don't often use them. Fair enough. Okay. Where are we going with this? Boom. What is the future of ESLint compared to new Rust-based tools like OXC? OXC, Biome, Dinolint? Very excited about that. I was also excited to see other speakers touch on this shared AST stuff like Evan yesterday and Anthony. There is not a single mainstream linter out there that can completely compete with TypeScript ESLint now. We have typed linting and no mainstream linter such as Biome or OXC does. However, that is not going to be the case forever.
Faster and Easier Linting with Biome and OXC
Projects like Biome and OXC offer significantly faster and easier to configure linting. Another project, TSSlint, is also working in this space. Favorite ESLint rules include no floating promises and rules that enforce good promise usage. Additionally, there is a deprecation rule that helps identify the use of deprecated APIs in TypeScript. As for book recommendations, the speaker suggests their own book.
I would highly encourage anyone interested in significantly faster or easier to configure linting to go look at and even contribute to projects like Biome and OXC. They're filled with really, really nice people and I'm excited about it. There is also another project called TSSlint, which is also working in this space. Not to be confused with TSLint, which is the old deprecated thing that predated TypeScript ESLint that I helped kill. Great. But yeah. They're very good. They're very fast. A lot easier to configure. At the cost of they're still newer, so they're still getting feature parity. They're newer, so they can move faster as well, which is really cool, I guess. Yeah. Get involved. If you want to see it, get involved. Yeah, for sure. Love that.
Do you have any favorite ESLint rules? Favorite ESLint rules? Oh my gosh! Yes. No floating promises. Which says if you create a promise, then don't just let it float away. Make sure something like try-catches it or stores it in a variable or passes it to a function. We're actually adding a bunch of features to that rule because I know it's kind of hard to work with sometimes. That await venerable no misused promises. There are a whole bunch of TypeScript ESLint rules that help enforce good promise usage to avoid async await shenanigans, which I really like. Also there's a deprecation rule, which is awesome, which just lets you know if you're using deprecated APIs in TypeScript, which is bizarrely helpful in enterprise. Any deprecation rules, yeah. Also... Move into the modern stuff. Yeah.
Do you have any good TypeScript book recommendations? Any good TypeScript book recommendations? Yes. Obviously mine is great.
TypeScript Books and Component Syntax
The second edition of effective TypeScript, authored by Dan Van Der Kam, is highly recommended. Stephan Baumgartner's TypeScript cookbook provides practical hands-on solutions. TypeScript should not add run-time types, but libraries like ArcType can be used for specific use cases. TypeScript does not currently support component syntax and render types, unlike Flow.
Blah, blah, blah. But effective TypeScript edition 2 just... Yeah, second edition just came out from Dan Van Der Kam who authored the type predicates feature in TypeScript 5.5. It's an excellent read. I like it as, among other uses, a sequel to learning TypeScript. It really dives in and explains really a lot of best practices and things to avoid all over the place, along with why those are the case. Cannot recommend effective TypeScript enough.
If I can jump in as well, I read Stephan Baumgartner's TypeScript cookbook. Yes, the TypeScript cookbook. And that is full of very practical hands-on using TypeScript and problems that you may come across and solve. So I really liked that as well. Yeah. The cookbook's great.
You talked about the type comments in JavaScript, but should TypeScript become available at run time? Yeah. At run time TypeScript? TypeScript should never add run time types. That's not something we should or could build into a typed superset of JavaScript. That is supposed to be used the way TypeScript is. However, there are a lot of libraries you can use to add those in, if that fits your specific use case. I would encourage you to check out ArcType. It's a really cool library from David Blass over in Boston, where I'm moving in August. Woo! And it does a lot of really cool type shenanigans. Nice.
OK. Will? This is another, Will, TypeScript has support for things you may or may not know. Do you think TypeScript will add support for component syntax and render types? Apparently Flow has it. Yeah. Actually, plugging to Flow, Flow has this awesome component syntax that makes it easier to declare React function components and similar. We're not getting it in TypeScript until it lands in JavaScript, because TypeScript no longer adds new run time things, and that's kind of bordering on that. It's a different syntax than JavaScript, which TypeScript is afraid to do.
TypeScript Syntax, Type Theory, and ESLint
TypeScript is afraid to introduce a different syntax than JavaScript. When discussing type theory with colleagues, find a suitable context to avoid conflict. Timeboxing arguments and picking a type solution can help. ESLint and linters are not good at formatting, while Biome improves the experience. ESLint TypeScript does not replace TSC, and TSC should be used for TypeScript type check errors.
It's a different syntax than JavaScript, which TypeScript is afraid to do. They don't want a conflict. So yeah, if it lands in JavaScript, which I really doubt would happen in the next decade, but you never know, then we do. Wonderful.
Aside from giving talks at conferences, how do you avoid going into lengthy type theory discussions whilst arguing with colleagues about TypeScript? Well first of all, I quit my job. So I don't have colleagues! No colleagues! But when I did... Flawless. There's a time and place for these. If you're having a lengthy type discussion, that should be in a context and situation where you feel comfortable and they feel comfortable. Screaming at each other in a team meeting or over a pull request is not good. By the time something hits pull request, you should have a shared expectation of what types to use. Sometimes it just doesn't matter. Pick one and go with it. That's an esoteric topic for most people. Timebox the argument. Timebox. Cool.
You have opinions on this, I believe. Should ESLint also be responsible for code formatting? I had a really good conversation with Anthony Foo, I think three times now we've had the same conversation. From an implementation side, ESLint and Prettier or linters and formatters are very different. And ESLint and linters are not good at formatting. They structurally are not good at it. However, it's a pain in the butt having two different tools, which is part of why everyone is so excited about Biome, because Biome makes this a much better experience. So, fundamentally, I don't believe so, but I recognize why the ESLint stylistic project, which lets you use ESLint as a formatter, it's a lot of stylistic rules, is really nice. So, eh.
Does ESLint TypeScript make running TSC unnecessary? It's a great question. It does not make TSC unnecessary. I keep forgetting to look up if there's a plug-in that surfaces TypeScript diagnostics, which are the outputs, the squigglies, but no, we do not surface TypeScript type check errors. That's just not what we do. That's what TSC does. All right. Well, that is all the time we have for questions. Give it up once more for Josh. Thank you so much. Thanks, everyone. Thanks, Phil. That was great.
Comments