 I'm supposed to be doing this now, aren't we? All right, let's. There's our intro. OK. Excellent. YouTube comments. They are sadly a thing. They are sadly a thing. But we have been listening to them. Some of them, yes. The ones that actually have a point. Well, not all of them do. There's some good points that are being made. You know, recently increasing so, people have been noticing mind-pending boldness. That's something that has been coming up in the comments. Thank you for everyone who's been there. And noticing me that I don't ever let you finish a sentence. Has that been noticed? Yes. Oh, well, we could talk about that in a bit. But one of the things that we have noticed and listened to is people saying, when we talk about code, can we show some code? Yeah, that might be helpful. So could be nice. We've got a camera and a tech. We've got an iPad here with some code on it. So tree shaking. Oh. Let me guess. You're just doing this so we can put a nice buzzword in the title. Yes. 12 things you didn't know about tree shaking. Oh, yes. Number four will blow your mind. Class-based tree shaking is the title of this, I think. So here we go. We've got a code example here. I'm importing a load of stuff. Plugging your own library, are we? It's based on a true story. Like all good stories are. I'm importing a load of stuff. This file has a lot of stuff in it. But I'm only using two of them. And modern tools like roll up and web porting. Then why are you importing the other ones? Well, just to show that they're there. Yes. Technically, I wouldn't have to import them. I mean, commonly, I guess, you would import this as import IDB keyval from, like, put it all of them in an object. So you have, you know? No. No, you wouldn't. No, you wouldn't do that. I would do that. Good. So in this, each of these methods is individually exported. And that means that tools like roll up and web pack can go, huh, you're only using two of these or three of these. And it goes, well, I'm just going to take the ones you're not using and delete them. And that's tree shaking. And that's tree shaking. And that's good. Because the tool can figure out what you're using, because if you don't import them, you can't use them. That's how modules work, right? Right. So in the days where we would import jQuery, you've got 101 methods, and you're only using three of them. Tough. You were taking the full weight of jQuery. And with tray shaking, that's not true, because you're only using the stuff you actually import and use. So yeah, this is great. This works fine. But around to this problem. So I just said, this is a library, real library. And someone said, well, it's all fine having set and get and all of these things. But I want to create my own store. That doesn't clash with another store. I was like, well, I know how this works. So I made it happen. And so I thought, well, it could be like this, right? So I got. Now you're importing a store? Oh yeah, that's the comment. You now wouldn't just harker the thing, but you have to instantiate the whole thing first. And it knows all of its stuff about where the database connection is and all of that. And it can go. But the problem is, classes can't be tree shuck and I'm sure that's the right way of saying that. Oh, so OK, so you have a class. It's called store. In the constructor, as we can see here, it gets the backing store name, the IDB. What is it called a store in IDB? Yeah, object store. And then the class obviously has all these methods, like get and set, but also the other ones we saw previously, like keys and whatever that was. Yeah. OK, so but if you don't use one of them, ideally you wouldn't load the code, right? But it's not statically analyzable in the same way a function is. So here I'm using .keys, but I'm not using the delete method. I'm not using the clear method. But it has no way of being sure about that because keys like this, it kind of looks like, yeah, that's statically analyzable, but there are many other ways. Yeah, that's what I meant. You can do very weird things. Right, exactly. So you can do as a string, but that string could be like two strings added together, or it could be some sort of functional something. If I ever see anyone writing code like in the last line, I will hunt that person down. But there are legitimate reasons to do that. You might have a series of method names and you want to append on to the start or remove on to the start. Yeah, I've done it myself. Like if you build your own little metaprogramming thing where you generate event handles on a flight, this can happen in real production code. This is not you being stupid. This can't happen. It can happen. And so my question really is, how do we solve this problem? And spoiler alert, I don't really have the answer, but I've seen what other libraries have done. And so one example is this is a style of RxJS. So here we're importing the store. So we've got our store. Doesn't have the keys method on it because that's, let's say, a less common method to call. Sure. But you import another JavaScript file, which has the keys implementation in it. And that just mutates the prototype? It mutates the prototype. Exactly. So this would be the implementation. I mean, it works. I totally get it. I'm always wary when suddenly the order of imports matter. I feel like that's a dangerous path to go down. And generally, mutating the prototype is, I mean, it's been done for years. I'm not saying it's bad or stupid. It's just saying it feels dirty. It feels like there should be a better solution. Absolutely. And part of the problem with this as well is if you import it, but don't use it, tough. Because that's not statically analyzable once again. Roll up or Webpack can't tell. So it shifts the burden on the developer rather than just being a tooling issue. Yeah. And it means you end up doing this import for every method. It's the kind of long strings. It's a bit messy. So yeah. So thinking about other ways of doing this, and there's a JavaScript proposal which I really like. I'm a big fan of, called the bind operator. Yes. I remember the bind operator. So here we're importing store and the methods. So store basically just in this specific number would practically more or less be an empty class, right? There's not much in there. Exactly. And you will call it like this. So store, call, and call, and set. And that's essentially saying call this set method as if it were an instance of store. If you have a function in JavaScript, you can use dot call. You cannot just use parentheses to invoke it, but you can use dot call. And then you give it what should be this inside the function, like this, what is this supposed to be. And yeah, here I have it. And what the parameters are. So in the bind operator just says, take my left side as the this, and the right side, just do a normal invocation. In this case. Exactly. So the store set function kind of thinks it's being called on store even though there is no tight coupling between those two things. Exactly. So you use this just as you would in a class. And this will refer to the store as it would within the class. And this can be tree shaken and all of that stuff. If you don't use it, it. I've used this in Babel a couple of times, but I don't think such has shipped yet anywhere. No. And this makes me sad that it looks like the whole proposal is dead. That is sad. That it does make me sad. Do you know why? Well, because another proposal has started taking kind of caught people's attention for doing a lot of the same stuff. And this is the direction that the RX folks have been looking at. So same again, you import the store and the separate methods. They've been the same as before. But. Ooh. OK. So this is the pipeline operator. What's the difference? Well, so what this is saying is call, take the right-hand side, treat it as a function, and pass the left-hand side to it, and call it. So set right now is a function that you invoke and it returns another function. Yeah. Great, isn't it? So that's, yes. So your implementation of set would look like this. So here we've got a function, which returns a function. The first one takes the key and the value. And the second one takes the store. I see. I mean, the ugliness is hidden, but it is ugly. Yeah. Yeah. And this is the way the sort of RX folks are sort of looking at. I think it's OK. I think you're right. Like writing it is confusing. Explain to someone that, oh yeah, this is a function that returns a function. That's how it works. So I think I've seen this operator before, the exact same operator in F-sharp. Yes. It works differently there, though, because there, basically what is on the left-hand side will become the first argument of the function of the right-hand side. So in this case, it will become the first argument, but it will be like. But of the function it returns. I see. That would be basically injected in front of the other argument. So you don't have the necessity to create a new function first before you can start using this. So there is an alternate proposal, which looks like this. Here, you're using a question mark to say where store would be passed into. I see. And this is sort of the hack style of it. So where is this at? So this is stage two. There are like two main competing proposals for the pipeline. And then that has spawned like another 12T7. Variants of the two or ways of trying to combine the two. So yeah, it's very much kind of experimental, still discussing the feature's land. But I keep going back to bind for things which are instance methods. And I feel like even if this ships, I feel like I would end up going for something more like this. Oh, that's actually not too bad. Like where I have a do method that takes. Legitimate under the hood probably switches it around. Which legitimately under the hood is just going to do. Yeah, it's just going to take the first one, the arguments. This. Exactly that. I like this pattern, honestly, because this you can do today. And it would allow you to do the tree shaking. Exactly. The downside to this pattern is I don't think it's possible with TypeScript, which I know shouldn't hold you back from JavaScript. Why not? Because in the dot do case, the second and third and to infinity arguments, their types are depend on the kind of thing. You can do that, but then the type would have to know about all possible functions. Exactly. It's like they do with event listeners, where they define the type depending on the string value of the first argument. And then that's what the event type will be. So you can do that with a string. I don't know if you can do it with an object. You maybe can. Good question. I actually don't know. But it's definitely more complicated than it should be. So yeah, that's the problem. I have to say that that is probably the best solution I've got or just a function which will take the store object and just be able to bind operator. Or just be able to bind operator. It's still in there. The plug-in still exists. Yeah, but to go for something which is not going to be pursued in JavaScript maybe, it feels like the wrong direction to go. I don't know. There's one more proposal which is kind of just being talked about, which I kind of like. And it would be a way of having an instance in a declarative way of saying, take these extensions and apply it to this class, but only in this scope. OK. And so it's a kind of way of, you know. It's very specific to this problem then, though, because I feel like the bind operator would be more powerful, generic, or a better solution of the bind operator would be a more generic, more powerful tool to have. And that is, yeah, that's my worry about it as well. Is it solving that specific problem whereas bind solves that problem and lots of other problems? Yeah. So yeah, I'm curious to see where it goes. We've got hacks we can use in the meantime. Yeah. But I just, yeah, I want bind all a way to do this in TypeScript, which might already be possible. And if so, someone should tell me in the comments. And this is me farming off my work to other people. Should we introduce zero HTTP codes? Negative, very specific. What if we reach 100? Oh, what do we do when we actually shoot HTTP 203?