John Reilly
John Reilly
Long-time Londoner, born in Bristol and raised in Fleet. I blog at https://blog.johnnyreilly.com and I work/have worked on a number of open-source TypeScript projects including: - Definitely Typed - ts-loader - fork-ts-checker-webpack-plugin I also wrote the history of Definitely Typed: https://blog.johnnyreilly.com/2019/10/08/definitely-typed-movie.
'TypeChat' Panel Discussion
TypeScript Congress 2022TypeScript Congress 2022
39 min
'TypeChat' Panel Discussion
Video
Hello all, I'm John Riley, you know me. Would you like to describe yourselves? So let me have a first crack at this because I think Nathan, you've been part of the TypeScript team for the longest time. Gabriella, I think you're a recent joiner, and Titian, you're not part of the Tech Stream, you're part of Bloomberg, but you contributed to TypeScript. That's me sort of like mangling your intro, so I wonder if you could try and introduce yourselves a little bit more in depth. And also tell us your journey to TypeScript. You want me to start? Yeah, go for it Nathan. So I'm Nathan Shively Sanders, and I've been working on TypeScript I think for six and a half years now. Yeah, six and a half years. And before that I worked on another compiler at Microsoft, and before that I studied linguistics in grad school. And so all told, between starting on the TypeScript compiler, it had been about a decade since I'd written any JavaScript at all. And I just was looking for a different compiler to work on, and TypeScript seemed really cool, and I tried it, and it turned out to be a lot of fun. Yeah, so that's me. Amazing. Thank you. I've got a good one. What was the compiler that you were working on before that? It was an internal thing, which I think was briefly sold as uSQL. It was like somewhat marketed as a successor to tSQL, except it wasn't, and then it turned out nobody wanted to buy it. So it was for sale for a very long time. But it's a SQL dialect, yeah. Nice. Thank you, Nathan. Gabriela, could you tell us your story? Yes. Sorry, there's a very annoying fly here. Sorry about that. Yeah, so I have been working on the TypeScript team since last year in July. So everything TypeScript is very new to me. And I got here because I did an internship at Microsoft working on a front-end project, and that's how I got to know TypeScript. And so I thought it was pretty cool to have Types in JavaScript. And I emailed someone from the TypeScript team, and they did a few internships, and here I am now. Nice. That's really cool. Titian, tell us your story. Yeah, I'm originally a C Sharp developer. I actually didn't have much love for JavaScript, quite frankly. And when I first saw TypeScript version 0.8, and I saw the types, and I saw I can just press dot, and I get accurate code completions and all of that productivity enhancements, I was like, yeah, now I can do JavaScript. That's what I want to do. And I've been a huge fan of it ever since. So the rest is history, as they say. Yes, yeah, no, I had a similar feeling. Like this is the thing that I need. First question. So when you think of TypeScripts, and it's an amazing thing, obviously, but you must have, as language implementers, people who've worked on languages, regrets and mistakes around it, things that you might do differently, like knowing what you know now if you were to go back five years, say. I'm curious if there's any of those that you've got in mind that you could share. One thing that I wish we could improve or maybe get rid of entirely is enums. They seem like a feature that should be useful, but the way they're implemented in TypeScript just isn't very strict, except when it is strict, and they're just really complicated without actually providing too much benefit. And if we were to do them today, we have a bunch of features like with unions. So enums actually predate unions. We tried to retrofit union semantics on top of them and didn't really succeed. That's one thing I'd either get rid of or change. I'm not sure which one. I don't know if you all ever use unions. I'm sorry, Sam? Yeah, I very much share your opinion on this one, actually. I remember enums being there pretty much from the beginning and not really using them. I didn't like the fact that they had a MIT aspect to them. And then union types came, string literal unions came out in like, I want to say it was like 1.7 or 1.8, something like that. And I was like, I don't need it anymore. The compiler does exactly what I need in that space just using this instead. I can now forget that this ever existed. And that's how I've rolled with regards to enums since then. Yeah, I mean, for us at Bloomer, for example, we actually use a pattern of creating an object and using as const on it and sort of emulating a union rather than using actual enums. I think for us part of the deal breaker is sort of their sort of nonstandard. And that's why we've sort of steered away from them. But I think that sort of speaks to a broader theme of, you know, like most of the things that came into TypeScript before TypeScript adopted the strict philosophy of just JavaScript plus types. I think a lot of those are sort of, at least from my point of view, features that people will try to avoid at present anyway, for example, namespaces and other things like that. Yeah, there's a weird corner of the language I'm embarrassed. I think it was my first feature on the team was this parameters versus you can have a normal function and you can say this colon and inside the function, it'll pretend like this has that type. So you can sort of use it to sort of write extension methods kind of thing. Not really. Yeah. But at the time I didn't realize it. And it's sort of the last feature we put in that's in expression space. In other words, it's valid JavaScript, except that TypeScript lets you write something that shouldn't be able to go there. Yeah, but that feature is actually very useful. I don't think I mean, I don't think you could take it out of TypeScript. No, you can't take perhaps another syntax for it, but it definitely would have to be there in some form. And I think the reason was I've been writing a lot of C sharp in the years beforehand, and it seemed like a natural place to put it. And everybody on the team was like, yeah, it seems good, except I think Ron pointed out that he's on the TC39 committee. He's not going to like this, but I didn't know at the time. And so we got in. I think that's probably the last thing we did that sort of takes over expression, JavaScript expression space. Yeah. Like it's funny, I know that TypeScript doesn't do like semantic versioning, like everything can break with each version kind of as like new language features come along and the compiler becomes stricter and that breaking changes like thing is actually kind of like useful, like because you want your compiler to get better and better and find more and more errors and make your code more and more correct. But at the same time, like I think nothing has been kind of like removed from the language since like 1.0. Nothing's like radically changed since then. And I've always wondered, like given that there's already like an understanding that breaking changes like are a thing. And I think that TypeScript like will do like removing like parts of the language that were like reliably agreed, okay, this is the thing that we don't want to have, like this creates problems. I was wondering if that could ever happen. I think the answer is no, but I'm like, could it? Could it? Maybe? I mean, so I would say as long as TypeScript is part of Microsoft, the Microsoft philosophy is supporting customers as long as possible. Yeah, that's so basically the answer is no. And typically inside of Microsoft, we have some very old code bases that still in theory, somebody from that maintains that code might come to us and say, hey, I need your help with this. Please make the TypeScript compiler stop crashing or run faster or work with this new feature all of a sudden. And we try to give the same guarantees to the people outside Microsoft too. If there were a TypeScript that was sort of outside Microsoft and untethered from the Microsoft philosophy, it's possible, but I don't see that day coming because TypeScript is just so integrated in all of Microsoft's properties at this point that it's something that it's not going to go away fast at all. Yeah. Yeah, that's a really interesting question. Like what would a TypeScript successor do that started over today? But it's not one that the TypeScript team can really do anything with, I think. I think it'd be very cool to see what other people would do. Gabriella, you've got like more recent eyes to TypeScript given that you joined like relatively recently. I wonder if there's, as you look at something with new eyes, you often like form different perspectives than the people who've been looking at something for like 10 years. Are there things that you look at and you're like, that bit there, I think that that thing there could be different or should be different? Yes, I think that has happened quite a few times since I started. Once you start working as a language implementer, there is a lot that you start taking for granted and that other people that are just users of TypeScript, they don't know the internal knowledge of the compiler. So sometimes they can't make sense of what's really going on when say there's a weird error message. I know Arthur was talking about this on the last talk and it has happened quite a few times that I see an error message and I go up to the rest of the team and ask, hey, what is going on here? This doesn't make sense to me. And then someone else from the team comes and explains it in terms of the compiler internals. And so in light of how the compiler works, it makes sense, but a user wouldn't know what is going on. And we then try to make that better so that people can understand what's the problem with their code, even if they don't know exactly how the compiler is computing all the types. Have you seen a Matt Pocock's TypeScript error translator experiment? Yes. I took a quick look. What did you think? I think it's very nice. I would love to see some work on making error messages more accessible. And it's a really tough problem, right, because there are some cases where you can immediately tell, I mean, a compiler could immediately tell what is wrong. But sometimes that is not the case. Sometimes it all comes down to the intention of the user. And the compiler can't really figure out intention as easily as a human could. So I feel like there is always this tension between the user, what the user means, and making sure the compiler can understand that. And it's not always possible, but I guess we are doing our best. Yes, definitely. I really like the shape of that solution. I think it would be pretty good if, like, interactively VS Code could give you a link underneath an error that you click and it takes you to some page like that. I really like the way ESLint rules have it. This is okay, this is an error, this is an okay, this is an error, this is okay, this is an error. ESLint just has lots and lots of code examples for every lint rule. If we had something like that for error messages, I think it would help people understand by example rather than whatever words that we try to stick together to explain what's wrong in one line, which is sort of what we try to do now. I don't know, at least in my experience, part of the problem with error messages is also just the sheer amount of information that has to be in them. For example, if you're trying to assign one union with 100 members to another union with 100 members and you get them all expanded out in there because probably that doesn't have an actual name or it's just expanded out for some other reasons, it becomes impossible to read. I think some VS Code support there to be able to expand error messages, to be able to interactively look at them might also be useful. Right now TypeScript only has one shot to provide you all the information it's ever going to provide. It just gives you the whole error message and it has to stick as much information in there because it doesn't know exactly what is useful. Like Gabriel said, it can't figure out your intention and what part of the error message is important is probably also based on your intention. Some interactivity there might also be beneficial to help you drill into it more to your own leisure rather than just spitting it all out in front. That reminds me of another idea I had when we were talking about improving the development experience for JavaScript users. Since VS Code uses TypeScript to do the IntelliSense for JavaScript as well, that means if you have Lodash and you have an error in Lodash, in JavaScript we're going to give you this extremely complicated type error, assuming you have Check.js on. Some people with Check.js on will be TypeScript developers and they want the full detail. I think a lot of JavaScript developers might want Check.js normally to tell them when they're adding a number to a string, they don't necessarily want to know that when they say underscore dot map, that the thing that they pass to it has to be array-like or map-like or iterable or this and then you get this error message that's a mile long and just not really appropriate for a JavaScript user. If you could do some sort of interactive expansion, the way Teachum was talking about that, I feel like you could give something simple to JavaScript users and then expand it if they wanted to. I've got a question from the community. This originally came from Mattias, also known as Anderish Drake. I had to look this up when the question was, partial inference, when? I had to go and look up partial inference. I hadn't heard of it, I didn't know what it was. When I looked it up, it was like, this is quite a complicated thing. I wanted to ask you that question, but before we get to the answer, I wonder if someone could take a stab at explaining what partial inference is because it's somewhat complicated. You want me to try it, Gabrielle, or do you want to try it? I can try it. Go ahead. I said you can try it, I think you have a better context. Partial inference is basically, when you're using a function that has type parameters, say map is a good example, most of the time TypeScript can infer what the parameters are. If you're mapping over a list of numbers, then it fills in the type parameters number. Sometimes that doesn't work, particularly on really complicated libraries. I think there's some React libraries and Redux libraries are so complicated that they can't necessarily figure out what all of the type parameters should be. The problem is you have three type parameters, you have a really complicated type. TypeScript either forces you to have all of them be inferred, like you can't say what any of them are, and if it gets it wrong, then you're just out of luck. Or you have to say what all three of them are. A lot of the time, two of them will be easy to infer and the third one is really hard and you have to manually specify it. Partial inference would be the ability to say, okay, I want you to specify type parameter number one, but for the other two, just let TypeScript do its normal inference. We have a proposal actually, and a PR even, that hasn't gotten merged, and it uses star. Instead of number, number, number, you'd say number star, star. It would then say, okay, for the first parameter we use number, for the other two we just use normal type inference. Whatever TypeScript would do there is what TypeScript will do. I think that about covers it. The reason it hasn't happened yet is actually sort of work-a-day engineering problems, really more than anything. It seems like a good idea. The problem is that, one, because of backward compatibility, we need to make sure that type parameter defaults still work, which is another feature that says, hey, for this type parameter, you don't have to pass it, which should sound familiar. It's exactly what you wanted at the beginning of this feature. You don't have to pass it, but if you don't pass it, instead of using inference, we'll just use whatever the default is. In retrospect, that's sort of not the right thing. I think what people want most of the time is inference, and they don't necessarily want just a static type to be plopped in as the default. But unfortunately, that's what we shipped, that's what we're stuck with. There might be ways around it, and the current proposal probably would work. The problem is then it becomes confusing. Say you've got something that takes three parameters, and two of them have defaults. You can either say number star star, or you could just say number. If you say star star, it uses inference. If you say nothing, it uses the default. It starts getting really confusing to use. I just might have sensed a call site solution for that just seems rather clunky, because some of these functions have five generic parameters. So just go number star star star star star star, which just becomes really unmanageable. So I don't know. I definitely would like to see some sort of definition site solution for this, where you can specify, okay, this parameter you should infer even if the other ones are specified, something like that. I think that usually the people writing the function will tend to know what parameters should be inferred and what parameters should default. Yeah, I think that's pretty similar to an even earlier proposal in PR that almost had Rust-like associated types. I think that was part of the proposal. I don't think we ever actually tried implementing it, but it was basically a proposal for Rust-like associated types where you could say, given these input types derive some nested types, exactly like what you said, these things should be inferred or derived in some way from the problems that you did provide. And I don't know if there were any technical reasons that didn't work, or if we just didn't quite get the value. I feel like I remember being in the room during the design discussion and being very confused as to why this was better than type parameter defaults. And I think maybe if we went back and looked at it in light of the partial inference request, it might make more sense. So like I said, sort of normal engineering things where human engineers look at something and say, huh, I don't get why we want to do that. And then they move on. And then two years later, they'll come back and say, oh, that makes sense. And they'll look off. I mean, this partial inference, it surprisingly comes up very often. I mean, it seems like a very esoteric feature, but I see it on Stack Overflow. Every couple of weeks, somebody asks a question that would definitely need partial inference. And right now, what I would really suggest is, OK, use function currying or do something else and all sorts of weird workarounds that are compromises ultimately. Yeah, partial inference is pretty simple to use, I think, which is an advantage. It's obvious when you're using it, and you know what's happening when you do it-ish. Yeah, that's one of the things that we sort of think about when we're designing features is that new features sort of start off at minus 1,000 points and have to prove that they, one, will work with everything else in the language that's already there, and two, won't necessarily preclude us from adding things in the future. And that's one of the unfortunate things that type parameter defaults did was sort of wall off space, design space from us. And now we're sort of extra careful about adding things in that space because it's already sort of a mess, and we think, well, maybe this new thing will make it more of a mess. So, yeah, we should probably look at it again, though, because it's definitely highly requested. Yeah. I think Josh Goldberg wanted to send a cake to see if that would make you consider it some more. I think it probably would. The problem is that we're all distributed now, and so you'd have to send us like five or six cakes. It's all like, prearranged. It's pretty new. I'm super curious about, like, there's lots of TypeScript variants, descendants, implementations these days. So, like, AssemblyScript and TypeScript Plus, and I'm curious about, like, what's the difference between those two? And what do you, do they affect the way that you work on TypeScripts, like, knowing that there's these things out here that are sort of like looking to it? Or, yeah, what's your take on them? Well, probably T-Chen can talk about this a little bit more, but one of the interesting things actually, in terms of, that we do think about in terms of downstream tooling is stuff like Babel or, you know, SWC, things like that, that people use for emitting TypeScript fast. We're actually kind of happy that those exist because we would ideally like to be in the business of type checking and have people rely on our emitter less than they do even. And I think that's a good thing, and I think that's probably going to keep growing as TypeScript becomes ubiquitous. People are going to want to just have TypeScript support built into whatever tool they're using. And that frees us up to do the hard, you know, really difficult type checking stuff and let other tools do something that's fast and sort of syntax-based. And I think that Bloomberg was looking at something like that recently. I don't know if you wanted to talk about that. Oh, yeah, we're looking at sort of a proposal to create sort of a mode of TypeScript where you have to specify all your types. And I know that that's a rather contentionous issue, I mean, to specify all your types on things you export from a module. And I know that's a contentionous issue because a lot of people like to infer those types, and I personally like it a lot as well. But that would free up things like emit generation without the type checker. Because right now, if you want to emit, for example, a function and you don't specify the return type, well, the type checker is the only one capable of actually creating that type because it's the only one that's going to actually have enough information to be able to synthesize that type. But if you were to specify it, then what you would get, you could get the benefit of having external tools being able to just syntactically create the declarations because you just have to remove the body and preserve the signature, and then this could be potentially much, much faster. And the advantage of this, I mean, for us personally, we have sort of workspaces with a lot of projects in them. Building these can take a long time. But what you would get through this is you would be able to parallelize more because you don't have to wait for the type checking to finish on the upstream project. You could just emit the declarations and let the downstream project already start building before you finish type checking on the dependency project. So we're really excited about looking into that. And it seems like we could get a lot of performance wins from that with regard to build time. But the problem is you will have to specify your types, and that is probably going to wall off some use cases. I think also mentioned earlier on isolated modules and the great advantages that they brought to the ecosystem as a consequence. I think this proposal is called isolated declarations. And does it bring potential similar benefits in the longer term, do you think, if it becomes a thing? Yeah, I think it would be a huge win. You could use Babel to emit or whatever other fast you could write your declaration emitter in Rust or whatever else you wanted to. And just, again, do a simple syntactic transformation of your original source code into a declaration, which would be much faster than what TypeScript has to do to infer those types. And even potentially the TypeScript declaration could be much faster because right now synthesizing those types can be a pretty massive amount of work, especially since you're not writing them. TypeScript will try to take a best guess at what you would have written there. And sometimes that works out well. Sometimes it might expand out things you don't expect it will expand out because you're using type aliases or something else. And that has definitely improved in more recent versions. But for example, in Bloomer, we saw declarations that were this big and they don't fit on screen. And that just came because we were using a lot of inference in our return types. And you just don't see it. You don't realize it because declarations are not something you usually think about when you write that code. Yeah, that's very true. People would end up with a megabyte DTS file. And they didn't realize they'd done this because they returned some complex value whose type was so hard to write down. If you actually write it down, you end up with a megabyte of text. And isolated declarations would just make the compiler stricter. You'd have to write it yourself. And once you wrote it yourself, you'd realize, oh, I'm returning something really complicated here. Is there some more simple way that I could write it? Because presumably you don't want to write down a megabyte of text. Hopefully. You could use a generator to just write it out. Yeah, exactly. I was thinking about other typescript variations or variants. Those are sort of stricter things. TypeScript Plus is interesting because it's basically trying to use js.comments to annotate your code. I think they have extension methods and operator overloading. So it's like a variation of the compiler that reads a js.comment that says, oh, yeah, when you say plus on these two things, the compiler should definitely treat that like you'd actually called this function over here to add them in some way. So you can get operator overloading. And talking to the creators of TypeScript Plus, I realized that some people really like the type system combined with JavaScript. I always have to keep reminding myself that people really like a somewhat creaky combination of really complicated types on top of JavaScript. And it's not just sort of an engineering requirement. Because from the inside, the compiler sort of feels like, hey, we're making this type system so that JavaScript can have types. And this is sort of the best we can do. And we're never going to be as good as languages like, you know, standard ML or Haskell or something like that. They have from scratch designed type systems. But some people quite like TypeScript's type system, even though it sort of has a bunch of weird corners and lots of strange features, basically. I'm a fan of it, definitely. And I just wanted to ask you, do you think we could ever see TypeScript for other runtimes? I think that sort of, but not just a subset of it. I mean, the full TypeScript. Because I know it seems like it's so tied to what JavaScript does. I don't know. I think that it basically cannot survive outside of the JavaScript ecosystem on its own. I mean, static TypeScript is TypeScript that compiles to assembly, but it's really, really restricted. It's extremely restricted. So it's not nearly all of TypeScript. And I think it's on a fairly old version by now. So I mean, in theory, it could exist. I mean, the part that I like about TypeScript is the maps types, the conditional types, all of that goodness, which I, as far as I know, static TypeScript doesn't support. I mean, that's the part I find interesting. So I don't know. I guess it would be much more difficult to do that at runtime without the current support from JavaScript. You're sort of imagining like REST, but with TypeScript's type system almost, or something like that, or maybe ML, TypeScript type system. Yeah, that's interesting. I mean, it's in theory possible. You just have to basically find somebody who liked TypeScript enough that also needed to emit really fast code. Why not the TypeScript compiler? I mean, that should be really fast. Yeah, I mean, we're sort of focused on providing types for JavaScript. So I feel like that's sort of the overriding message about TypeScript variations is that the TypeScript team is really busy providing types for JavaScript. And that's what we're here to do. And so I would personally love to see more variations on the TypeScript idea. It's just that I've never had time to do any of it. Because yeah, I mean, at the end of the day, we need to help people ship websites basically, or Node apps. What would you say are the things that are most interesting for you in TypeScript's future? Like what are the things that are in the pipeline? You're like, oh, that's the thing that's going to be amazing and game changing, or the optimizations. What are the things that excite you about the things that you're working on at the moment? I can see Gabriela's flyers. Pestering. Well, I mean, one area when I'm interested in is improving the JavaScript experience. Because in JavaScript, you're not writing any types by default. And a lot of people who are writing JavaScript have never heard of TypeScript and are sometimes just beginning programmers. And I think there's a lot of work we could do there to improve just sort of the out of the box experience of programming JavaScript. Not sure exactly what form that would take, but I think there's a lot of things we can do there. Are you talking about like JSDoc support? I'm guessing you're not talking about that, because if you're new to JavaScript, you wouldn't necessarily be thinking about types at all directly. Yeah. Well, here's what I'm talking about. So a pretty old example is I was talking about how you if you're using Lodash. So in VS Code, if you import Lodash from a JavaScript project, in the background, it's going to download at type slash Lodash, show types for it. And then when you say underscore dot map, it'll show you the type for Lodash. And that's useful. But the experience there could be improved. And then if you're writing your own code, for example, if you're using, say, ES modules, and you export and import, the TypeScript finder is going to tell you what's available and what's not available. It'll automatically import things for you. And that's nice. But we don't do anything with trying to figure out what the types of code that you wrote in JavaScript is. And there's probably something we could do there. And just the error messages are bad enough if you've signed up to use TypeScript. If you're using JavaScript, you get an error message. I mean, what are you going to think, right? If you get this a mile long error message? Yeah. So we just don't show most error messages to JavaScript users right now, by default. Really nice if we could show some of them by default, if we knew, hey, that thing, we're almost exactly certain it's a string and passing it to something that we're almost exactly certain requires a number. Let's put it in there. And we don't today. And we could help people with a lot of just the same silly mistakes that TypeScript prevents. We could prevent that in JavaScript as well. I think that's one thing I'm interested in. But I mean, the isolated declarations is actually a pretty cool idea, too, because I feel like that helps the ecosystem quite a bit, letting people build big projects faster. Awesome. Yeah, I think that's a really great note to end on. I want to say thank you to all of you for joining us with this chat. It's super interesting to hear the decisions that go into making a language and the choices around evolving it and that kind of thing. It's also, I think, really cool to hear feedback from the community on things that they're really excited about and getting directly from you the why's and the wherefores and the considerations that go into that, because there's clearly a lot of input into making decisions around these things. So, yeah, thank you so much. Thank you so much.