Stop Writing Your Routes

Rate this content
Bookmark

The more you keep working on an application, the more complicated its routing becomes, and the easier it is to make a mistake. ""Was the route named users or was it user?"", ""Did it have an id param or was it userId?"". If only TypeScript could tell you what are the possible names and params. If only you didn't have to write a single route anymore and let a plugin do it for you. In this talk we will go through what it took to bring automatically typed routes for Vue Router.

30 min
12 May, 2023

Video Summary and Transcription

Designing APIs is a challenge, and it's important to consider the language used and different versions of the API. API ergonomics focus on ease of use and trade-offs. Routing is a misunderstood aspect of API design, and file-based routing can simplify it. Unplugging View Router provides typed routes and eliminates the need to pass routes when creating the router. Data loading and handling can be improved with data loaders and predictable routes. Handling protected routes and index and ID files are also discussed.

Available in Español

1. Designing APIs: Challenges and Considerations

Short description:

Designing API is really hard. It's one of the biggest challenges of any open source library. A good API makes errors hard to make and avoids context switch. Writing different versions of an API and considering the language used are important. The learning process for an API is subjective.

So yeah, my name is Eduardo. Good morning, London. Happy to be here another year. So as a Querty member but also as a developer and open source lover, I've been doing a lot of development of libraries, almost for seven years I think. So not only PNIA and Vue Router but also some of the libraries that are just adjacent to Vue itself. And I have been spending quite a lot of time thinking about how do we design the APIs for these libraries. Sometimes messing up, making mistakes, sometimes improving them afterwards, of course. But the bottom line is designing API is really hard, okay?

And I think it comes without saying that this is one of the biggest challenges of any open source library because you have to factor a lot of, I'm sorry, you have to take into account a lot of different factors. It's from how does these API changes, wait, sorry, I need to change the thing. This is going to be painful. Okay. So you have to take into account a lot of different things into account. Okay? You have to factor the users you have, are you building a new API? Are you not building a new API? And how the API feels to users, because at the end, an API being good or bad is very subjective. And I'm going to show you why.

So one of the things that I feel is very important to a good API is to make errors hard to make. Now, it might be obvious to some and completely new to others, but if you use a library where making errors is actually easy, it makes you feel dumb. Now, nobody likes to feel dumb when they're using something, are they? So it's definitely a big factor in my opinion of how an API can be good or not. Another big thing is avoiding context switch. Now, when we think about APIs, we first think about the code we need to write. But if the actual API goes beyond the code we write, it's not only the files, the folder that we have, but we can actually think about many other things that are part of the API because when we write code, when we develop a program, we're not only writing code itself. And then we have to cut it for different user experiences.

Now, this is very vague to be honest, but it's not the same to write a V1 of an API, so you only have new users, than writing a V2 of an API where you have existing users that are used to something. Also, you have to think about well, what language you are writing for is not the same writing in API in Java or Rust, than in JavaScript or TypeScript where things are evolving very quick. And I like to refer to this little joke, the user learning curve. So, the thing is our experience when learning something, which is also part of an API, the learning process is different and is subjective. So, the joke here is very simple actually. You have kind of like the time recently and then how much you can do with a tool. So, as you can see, Notepad, you can use it very quickly and you are not very efficient.

2. Different Tools and API Ergonomics

Short description:

Different tools have different levels of efficiency and productivity. Notepad is quick but not efficient. Pico allows for more functionality. Visual Studio has many shortcuts but can lead to decreased productivity. Vee, Veeam, and Nveam require learning but result in high productivity. Emacs and Spacemacs are powerful tools. This forms the basis of API ergonomics.

You have kind of like the time recently and then how much you can do with a tool. So, as you can see, Notepad, you can use it very quickly and you are not very efficient. Then you have Pico, which is just a terminal-based tool and you can do a little bit more things. Then you have Visual Studio, which you learn a lot of shortcuts, I think, and I believe the joke is that then you start digging too much into IDE and you spend too much doing things and then you become less productive. And then you have Vee or Veeam or Nveam, which basically you need to learn a lot before even being able to use it at all, but then you're very productive. And then you have Emacs and Spacemacs, which bend time and space, I think, because there is no way to do that in math. And so I'm going to use this as a base for what I call API ergonomics.

3. API Ergonomics and Erasing APIs

Short description:

API ergonomics is about how often and how easy it is to use a feature. It's not linear, but trade-offs are necessary. Common features should be easy to achieve and remember. Today, I will explore erasing an API and focus on keeping things together, reducing repetition, and improving the development experience. The router is a good place to do this, as routing is widely misunderstood.

Now, API ergonomics, I define it as how often do you use a feature, feature being a very vague and abstract concept, okay. And how often or how easy it is for you to guess how to use that feature. Have you used it before or not, you have to take into account all of these things.

Now, you could imagine this is something linear. Of course, it's not. And it's definitely not the goal of having this kind of API ergonomics being linear. In reality, when I think it's better, well, of course, the best case scenario is having something that goes like that. But as you can imagine that's really not possible in life, right? So, we have to have some trade-offs here. And I think this is something, I mean, this graph, this ergonomic line makes more sense and is actually good.

Now, if you compare it to the other one here, we can see that we're going to spend a lot of time doing the tasks that are easy to do, easy to guess. So, this makes us feel smarter because we can figure out the things by ourselves. So, in terms of the experience we are developing in our library, it's much more interesting. On the other hand, anything that is quite complex, an edge case, things that you don't do that often, maybe you do one project twice, so maybe once a year or less, those are going to require more work, maybe using different APIs, different options combining multiple things on the library itself to make things work. You don't have one option like in Nux where you just do SSR true and you have SSR, where you do just view, right? You have to set up the V server, you have to set up many things.

Now, I'm not saying Nux here is bad, quite the opposite, but I think there is a trade-off here to be found and that if we make common features easy to achieve and easy to remember, we are gaining a lot at the end of the day. So today, I want to explore this path by erasing an API. And I really mean erasing, so this is not a breaking change. We're not deleting, okay? We're not removing. We're erasing. And I want to show you a view router as an example. And I want to focus on three things. I want to keep things together, so this is to reduce the context switch. I want to reduce repetition, so just to iterate faster, to be able to write more in less time. And I want to improve the development experience by making errors harder to make or easier to spot both things at the same time. Now, I think the routing or the router is a good place to do that because the routing itself is widely misunderstood. And, honestly, I don't blame anybody who doesn't really understand that well routing because it's the land for ever changing APIs on the browser. Like, do we use hash. So, we used to do hash URLs. Now, we don't anymore. It's bad for SEO.

4. Challenges of Routing and File-based Routing

Short description:

Multiple ways of parsing URLs, different events and upcoming APIs, and the challenges of routing in an application. Error-prone behavior and the need for simplification. File-based routing as a solution.

And then we have, because of that, multiple ways of parsing the URLs which are totally valid and both works and maybe you can even use both at the same time. By the way, they don't even have the URL in the API name, sph-state. If you have history but still. And then you have multiple ways of parsing it like location.href and then the URL constructor will have URL search params. We have different events and we even have upcomings APIs which, as you can imagine, is not supported by all browsers like Safari doesn't have a word on these API which have been on an ongoing discussion for two years already. So, we don't even know where to go. At least, we don't have internet explorer anymore, but still.

So, on top of that, it's where a lot of the different things or your application come together, the routing. So, you have state on the URL. You have the UI with transitions or animations that can happen between the pages. And then we have the model like with data fetching, usually integrate that with the routing. And we have a ton of vocabulary, okay? And this might look like nothing, but when you have to remember the correct word when you're searching the documentation, it makes a big difference because you cannot find the actual help in the documentation. So, it becomes very frustrating. And on top of that, we have some error prone behavior. For example, you define routes this way having a path and name and then you can push with a name and you can push with a string. But what was it before? Was it slash about, was it about? And you're not going to get any error when you're writing this code until you go to the browser, so you context switch, see the error on the console saying, hey, there is no route name slash about. And it doesn't even tell you if there is another route name about. So, can we simplify all of these? Of course, I wouldn't be speaking here if we cannot simplify this. And I want to focus on one very simple part of the routing which is creating route, is the beginning of any SPA application. Now, when you create a route, you usually create a file. This is something that we can merge together. And I think this is going to be familiar to a lot of you. And we are kind of erasing the creating the route, creating the object, the route record. The problem that comes before is we still need to configure the routes, but we're no longer writing the configuration. So, how do we handle that?

And so, I want to do a little quick show of hands, who has used file-based routing before? Okay, almost everybody... Oh, there is a big difference in both sides. More than half of the people here. So, file-based routing is what allows you to define these routes array or even the route altogether. The router, sorry, altogether. By just having a folder structure.

5. Field-Based Routing and Error Handling

Short description:

Nuxt completely erases router creation, advocating for reducing code repetition while maintaining flexibility. Field-based routing provides predictable mapping and eliminates the need for multiple learnings. Tools can generate glue code, allowing developers to focus on the interesting part. Types and errors are crucial, aiming for precise errors instead of generic ones. Runtime types and literal strings can transform objects into real types. Generating params for each route can be slow and result in unreadable code.

Now, this is what Nuxt does. It completely erased the router creation. And I want to show you something similar and I want to advocate for it a little bit more. So, the idea and the main, the key point here is we need a way to reduce the code repetition, which is what's happening here, without compromising the flexibility, which is being able to configure the routes.

So, when we have field-based routing, what we have and what's very important is that we have one-on-one predictable mapping. So, we know and we have a few rules that we maybe learn once. We know that index dot view, index dot HTML just becomes a slash at the end. And we know that we even have the brackets, it becomes a parm. And the good thing is that because this is sitting right next to you on your files, on your editor, you see this every day. So, you don't really need to learn these multiple times, okay? You learn it once and then it's on your head, it's there. And because we have a one-on-one mapping, we can let all the tools generate the glue code so we can write the interesting part only, ideally.

Now, this includes the route records and imports which is kind of boilerplate. But also, we can have types that we could write manually but we're gonna generate themselves, so they are always correct. And also, other route meta and other things that are code beyond that. So, the idea here is we want to get an error if we write something like this. And we don't want the classic TypeScript error when it says string is not assignable to type A. Then you have three dots that you cannot even click. And then, you go something like never is not assignable to string. And you don't even know what happened in between. You want, ideally, a precise error that tells you, hey, this object is missing the ID property, right? This name does not exist. This condition is not possible. So, these are types and errors, okay? This param other does not exist for this route because we checked that the name is ID so the shape of the param is an object with an ID. And so, initially, I wanted to do this with type, with run time types which, it's a very interesting feature of TypeScript. So, you have what we call literal strings that we can actually parse and we can transform objects into real types. These all work, okay? And I did... So, the good thing is that you just need to take your routes array, you put these as const at the end, and then you can generate an object that contains all the params for every single name route. Now, the problem is that this is really slow. And it took me some time to test because when I started doing it, you start with a few routes. But then when I get to 50, I realize that I achieve nothing but just crashing the TypeScript server, which can be an achievement in itself, but it's not what I want from my day-to-day life in development. And on top of that, I have to say this is the most unreadable code I've written in my whole life.

6. Unplugging View Router: Basics and Typed Routes

Short description:

I've written a lot of languages and C and Prologue, but nothing compares to this code. I realized I had to go back to the basics and create a type that associates a route to types. Unplugging View Router is a library that works with different tools and provides typed routes. You no longer need to pass the route when creating the router.

And I've written a lot of languages and C and Prologue, if you know this language. So I've written unreadable code a lot of different times. But nothing compares to this code. And I did try very hard to make some of the things readable apart from the one-letter generics, which is just part of LifeScript life. And I'm not really ashamed, it goes even worse, okay? But I invite you to just check the link and witness the Turing complete TypeScript magic here. I'm not going to dive into the types of course, there is no point.

The thing is I realized I had to go back to the basics. We have to go back to something that doesn't crush TypeScript and that is easier to understand, that can be human readable even though we are turning into AI stuff. So what is the most basic type we can have to associate a route to types? So we have type params and stuff. And if we specify the name as a key and then we have some kind of object that define the different properties of the route. These are still human readable. And it becomes very powerful because we can use the key off of the map just to get all the names and then we can get the params of every different route. Now, the actual type is a little more complex but is still readable. And so the good thing is that we can apply these to any other helper type, I mean any other type that exists in view router and make them typed. So they no longer allow you to just pass a string on the name. It becomes a union of many different strings. And so this is where Unplugging View Router comes.

Now, I know it's not a fancy name. It doesn't have a cute logo like Pina but this is just because I want to stay as close as the name of the library, view router itself and also because it works with different things, Vite, DRAWLAB, Webpack, et cetera, et cetera. You can use it without any option. Now, this is not something new on itself when it comes to the file-based routing. It's something that has been existing for a long time, okay, since 2018, I think, Hattachine, another member of the VGS core team, made this. And even today, one of the most common plugin is Vite Plugin Pages by Han, I think. So I'm introducing other things. And this is specific to ViewRouter for some reasons. The idea here, and this is the cool part, is that you not only need to change all the imports from ViewRouter into ViewRouter auto. And this is going to give you the types that are typed based on your routes. So the thing is, you're still in control. You create the router but you no longer pass the route, which is the big boilerplate part of the routing, okay? Oops, sorry. That was a bit fast.

7. Typed Routes and Route Configuration

Short description:

You can modify routes at runtime or build time. By passing parameters, you can safely type the routes and see errors in your editor. When using useRoute, you can specify the specific route for a page. The way it works is by generating a big type route DTS file that allows you to configure route name maps and overrides for your router and functions.

You can still modify the routes already. And this is the runtime changing. You can extend the routes. You can also do it at build time. So you can, in your V configuration, add any routes and they will actually be typed as well. So your code will recognize everything.

So how does it work? How does it look like? So instead of just pushing an interpolation of a string here of a route. This is a Vitess example, by the way. What do we do here is we can pass the name, which is going to auto-complete here. So we can select the route we want and then we're going to be able to add the params object and that params object is going to tell us, hey, you're missing an ID here. As soon as I put the curly braces. And so we have the auto-completion and not the ID, the name. Sorry. But basically you get the idea. You can pass any param you want here and it will be safely typed so you don't need to switch to the browser to see a problem. You will see it right on your editor.

Now, when you get the route of, with useRoute, you have all the possible routes here that can appear in your application. But when we are in a page, this is name.ui, see the file name app up there? We know that there is a name param on the URL, okay? So how do we tell useRoute that this is the actual, we are sure this is the route that, this is the route high name? So we can pass a generic here. So I'm gonna write high, that bracket name. And then the route becomes one specific version of the application. And of course, this generic, as you saw, it didn't autocomplete. Now, I think they changed that in recent TypeScript, maybe five. But I also added the version that allows you to pass an argument because that one does autocomplete. So you don't even need to think too much about it.

Now, the way works is that it's, by generating, big type route DTS that you can configure, you have this route name map, and then you have some extra, so you have overrides of all the types of your router and functions. And then the idea is, so I was talking before of how we are making things that you do very often easy to do, okay? And all the things that are less common, harder.

8. Improved APIs: Data Loading and Handling

Short description:

The version that allows passing an argument does autocomplete. The way it works is by generating a big type route DTS that you can configure. The key is not to compromise flexibility while making common tasks easy. The defined page macro allows passing properties for route configuration. Data loading is a huge topic with different handling options. Watch on the params lacks state, errors, and SSR handling. Navigation guards become duplicated and verbose. Global navigation guards offer a convenient solution. Suspense on the surface is perfect but has some error handling and handles SSR.

But I also added the version that allows you to pass an argument because that one does autocomplete. So you don't even need to think too much about it. Now, the way works is that it's, by generating, big type route DTS that you can configure, you have this route name map, and then you have some extra, so you have overrides of all the types of your router and functions.

And then the idea is, so I was talking before of how we are making things that you do very often easy to do, okay? And all the things that are less common, harder. But the idea, and the key, is not to compromise that flexibility. You should still be able to do everything you were able to do before, which is the configuration.

So here is the defined page macro, which, well, I know we are doing a lot of macros here, define, define, define something, so just another one to remember, but the idea is you can pass all the properties you are using on the route configuration, on the routes The difference is that we are on the page, so there is no context switch, we are staying on the same component, we are defining things. And we can add anything we want. We can also have JSON blocks, or Yaml, or other things if you want. And so, the cool thing is that because this is going to affect the actual types, if you change it here, so I'm going to define page and change the name of this route to something else. So I'm changing my own name here, I'm going to save, and I'm going to get an error here because this name does no longer exist. So you get instant feedback like that, and then I change it just to make it match.

Closing that chapter, there's other things that we can make to improve the APIs. One of them is data loading. Now, data loading is a huge topic. But today we have different ways of handling, and this is, in my opinion, one of the reasons it's not such a great API at the moment. Or if there is an API, if there is no one API. So we have different ways to do it. We have watch on the params, but we have no only state, no errors, no SR handling. We have all the navigation guards, but it becomes duplicated, and it can be verbose, and it's definitely not typed, except with the plugin, of course. Then we have global navigation guards, which can enable you to create a custom data solution, and I will say this is the most convenient solution. And then we have suspenser weight, which I have a whole slide for them anyway. But they all have issues. They all present some issues that doesn't allow us to use them as data fetching solution. So suspense on the surface is just perfect. We just put a weight on the script. There is nothing as simple as that. And it has a few pros, like it's very straightforward to write, the most straightforward to write, to be honest. But it has some error handling. And it handles SSR out of the box.

9. Introduction to Data Loaders

Short description:

Data loaders are functions that return data and give you a composable. They provide access to data, loading state, errors, and handle SSR. Exporting loaders allows for reuse and avoids duplicating requests. Loaders can be typed by default and multiple loaders can be exported.

But it's still experimental, although it should be changing soon. And more importantly, it doesn't update on navigation. It's not connected to the navigation. It's connected to a component. But these are two different concepts in reality, although it can be coupled if you want.

And the data is limited to the current component. If you want to use something you fetch in a page, in other components, you either put it into a store or you pass it down as a prop or inject provide. But they have some issues.

So, what I want to introduce to you is data loaders. So, data loaders are just functions that return data. Okay? And then they give you back a composable. This composable, you can use it on the same component, but also in other places. And it gives you access to the data itself, but also loading state, errors and stuff. And it handles SSR, et cetera, et cetera.

Now, the key here is to export the loader. You don't actually need to write the loader here. You can write it anywhere. But it has to be exported by the page, so that the router knows this page is loading this function. Okay? This data. And then you can reuse it anyway. But this also means that we are completely duping requests. So, if you are getting the user profile in many places, you're using the user data in many places, we still do one request. We have all parallelization by default, but you can also make a loader depend on another loader if you want. And they are affordably typed, because you're just returning the data. If we don't write any type, it's still gonna be typed by default. You can explicitly type if you want, but it just works out of the box. And of course, you can export multiple loaders.

Now, the whole topic is a bit longer, and I don't have any more time. I'm already over time. But I invite you to check the RFC, which still has some time.

10. Predictable Routes and Less Boilerplate

Short description:

We make predictable routes with fail-based routing, allowing our tool to generate types automatically. This creates a less error-prone environment with less boilerplate and no context switch. Check out the slides on esm.eslash for more information.

The idea goes a little bit beyond that. Some client cache, some cache simple, some support for Apollo, Yafire, Suba Base, et cetera. And it's still experimental. To summarize, what I said is that we make predictable routes by having a fail-based routing, because we have a one-on-one mapping and we know how things are going. And this allows our type, our tool, to generate the types for us. We have, therefore, a less error-prone environment, sorry, because we have the errors, we have, we're more likely to not do errors without the completion. I know we have Copilot nowadays, but it still makes mistakes and the compiler doesn't. And so we have less boilerplate because no routes array and no context switch because we're still on the page. Sorry, I really went very fast because I'm really over time. Here are some links you can check. The slides are on esm.eslash, stop writing your routes, just the initials. It should be very easy. And thanks for your attention.

QnA

Handling Type Routes and Protected Routes

Short description:

You can use type routes without file based routing, but it requires manual work and is less error prone. The plugin does not support Vue 2. Handling protected routes with file-based routing involves creating a navigation guard or using Metafields. The unplugging ViewRouter functionality may become part of u-router as a separate plugin. Loaders can be defined in a separate file and imported into multiple components.

Thanks a lot, Eduardo. That was extremely interesting. And I love the design of your slides. They're like super sexy.

Okay. So, let's check out the questions. But before everyone's first one, can you use type routes without file based routing?

So you can use the type routes without file based routing but the idea is you're splitting up the generation of the types and the writing of the routes so you have some manual work to do, whereas the whole point of having this approach is that the types are automatic and you don't need to worry about it, so you're less likely to make errors, it's less error prone.

Ok, definitely makes sense.

Ok, so let's check out what we have here, does this plugin support Vue 2?

Vue 2? No, no Vue 2 support because the types on the router are quite different so it would be a huge, it's mostly a time question, I just don't have enough time to make it support Vue 2 right now.

Ok, maybe in the future or? Or even, I doubt it to be able to find the time to do it in the future but I invite anybody to copy the code and fork it for Vrouter 2, definitely.

Ok, you've heard it, an open source opportunity.

Then, the next one, how should we handle protected routes with file-based routing?

So protected routes, usually you create a navigation guard, so you would still create your own navigation guard, the same way. You have the router instance somewhere, so you just router before each or before result. There are other patterns that you can use with Metafields, you can define Metafields on the routes, that allows you to have pretty fine navigation guards applied to multiple routes. So one single navigation guard that is applied in multiple pages.

OK, cool. I think it's a bit more difficult to explain without a code.

Cool, makes sense.

The next one is, any chance of the unplugging ViewRouter functionality making its way to Yes, we'll probably go, I mean, in order to do that we have to go through an RFC first. The difference is that it's not, I mean most of the code is not runtime, right? Most of the code is built in. So it still comes as something that will be kind of on the side, so if it becomes part of u-router it will still be like a vid plugin that is exposed through a different path like u-router slash plugin or something like that.

Okay, cool.

The next one is, can you define loaders in a separate file then import it into multiple components?

Yes, you just need to export the loader from the page to tell the router that this page is using that loader. That's it. And then you use the composable anywhere. So you need to first import the loader and then export that import?

Yeah, you can also just do export. I didn't say it but you have two scripts, you have the regular script and then the script set up. So in the regular script, that's where you can export things, and that's where you can just do export something from something else or you can import it and then export it because you will still need to import it on the setup if you don't import it in the other script. The editor makes it very easy to get the right behavior because it just autocompletes.

Okay, definitely makes sense.

Handling Index and ID Files

Short description:

The number of index.vue and id.vue files depends on the routes and how they are searched. If you have routes with the same common path but different names, you can still find the files easily using the folder structure. It's like nodes in a tree, where the leaves may look similar, but the nodes do not.

And the last question is, won't we end up with dozens index.vue and id.vue files? When? Or No, won't we end up with dozens index.vue and id.vue files? Yeah, probably, but not necessarily. Depends if you have other routes that have the same common path, but you still search the route by the other name. If you have a users page and a user slash new, you have a user slash index and a user slash new.vue. So when you look up the files, you look up for users index, so or you probably use my user space ei, sorry. When you do a Control-P on your VSCode, so you will still find your way around very easy, because you still have the folder structure that prevails. OK, yeah. It's more like nodes in a tree compared to the leaves. So the leaves do look like each other, but the nodes do not. OK, perfect. Thank you so much, Eduardo. And feel free to ask more questions upstairs in speakers' Q&A part.

Check out more articles and videos

We constantly think of articles and videos that might spark Git people interest / skill us up or help building a stellar career

Vue.js London Live 2021Vue.js London Live 2021
20 min
One Year Into Vue 3
Top Content
Vue 3 may still sound new to many users, but it's actually been released for over a year already. How did Vue 3 evolve during this period? Why did it take so long for the ecosystem to catch up? What did we learn from this process? What's coming next? We will discuss these questions in this talk!
React Day Berlin 2023React Day Berlin 2023
21 min
React's Most Useful Types
Top Content
We don't think of React as shipping its own types. But React's types are a core part of the framework - overseen by the React team, and co-ordinated with React's major releases.In this live coding talk, we'll look at all the types you've been missing out on. How do you get the props type from a component? How do you know what ref a component takes? Should you use React.FC? And what's the deal with JSX.Element?You'll walk away with a bunch of exciting ideas to take to your React applications, and hopefully a new appreciation for the wonders of React and TypeScript working together.
TypeScript Congress 2023TypeScript Congress 2023
31 min
Making Magic: Building a TypeScript-First Framework
I'll dive into the internals of Nuxt to describe how we've built a TypeScript-first framework that is deeply integrated with the user's IDE and type checking setup to offer end-to-end full-stack type safety, hints for layouts, middleware and more, typed runtime configuration options and even typed routing. Plus, I'll highlight what I'm most excited about doing in the days to come and how TypeScript makes that possible not just for us but for any library author.

Workshops on related topic

React Advanced Conference 2021React Advanced Conference 2021
174 min
React, TypeScript, and TDD
Top Content
Featured WorkshopFree
ReactJS is wildly popular and thus wildly supported. TypeScript is increasingly popular, and thus increasingly supported.

The two together? Not as much. Given that they both change quickly, it's hard to find accurate learning materials.

React+TypeScript, with JetBrains IDEs? That three-part combination is the topic of this series. We'll show a little about a lot. Meaning, the key steps to getting productive, in the IDE, for React projects using TypeScript. Along the way we'll show test-driven development and emphasize tips-and-tricks in the IDE.
Vue.js London Live 2021Vue.js London Live 2021
169 min
Vue3: Modern Frontend App Development
Top Content
Featured WorkshopFree
The Vue3 has been released in mid-2020. Besides many improvements and optimizations, the main feature of Vue3 brings is the Composition API – a new way to write and reuse reactive code. Let's learn more about how to use Composition API efficiently.

Besides core Vue3 features we'll explain examples of how to use popular libraries with Vue3.

Table of contents:
- Introduction to Vue3
- Composition API
- Core libraries
- Vue3 ecosystem

Prerequisites:
IDE of choice (Inellij or VSC) installed
Nodejs + NPM
React Advanced Conference 2022React Advanced Conference 2022
148 min
Best Practices and Advanced TypeScript Tips for React Developers
Top Content
Featured Workshop
Are you a React developer trying to get the most benefits from TypeScript? Then this is the workshop for you.In this interactive workshop, we will start at the basics and examine the pros and cons of different ways you can declare React components using TypeScript. After that we will move to more advanced concepts where we will go beyond the strict setting of TypeScript. You will learn when to use types like any, unknown and never. We will explore the use of type predicates, guards and exhaustive checking. You will learn about the built-in mapped types as well as how to create your own new type map utilities. And we will start programming in the TypeScript type system using conditional types and type inferring.
Node Congress 2024Node Congress 2024
83 min
Deep TypeScript Tips & Tricks
Workshop
TypeScript has a powerful type system with all sorts of fancy features for representing wild and wacky JavaScript states. But the syntax to do so isn't always straightforward, and the error messages aren't always precise in telling you what's wrong. Let's dive into how many of TypeScript's more powerful features really work, what kinds of real-world problems they solve, and how to wrestle the type system into submission so you can write truly excellent TypeScript code.
JSNation 2022JSNation 2022
141 min
Going on an adventure with Nuxt 3, Motion UI and Azure
WorkshopFree
We love easily created and deployed web applications! So, let’s see what a very current tech stack like Nuxt 3, Motion UI and Azure Static Web Apps can do for us. It could very well be a golden trio in modern day web development. Or it could be a fire pit of bugs and errors. Either way it will be a learning adventure for us all. Nuxt 3 has been released just a few months ago, and we cannot wait any longer to explore its new features like its acceptance of Vue 3 and the Nitro Engine. We add a bit of pizzazz to our application with the Sass library Motion UI, because static design is out, and animations are in again.Our driving power of the stack will be Azure. Azure static web apps are new, close to production and a nifty and quick way for developers to deploy their websites. So of course, we must try this out.With some sprinkled Azure Functions on top, we will explore what web development in 2022 can do.
TypeScript Congress 2023TypeScript Congress 2023
131 min
Practice TypeScript Techniques Building React Server Components App
Workshop
In this hands-on workshop, Maurice will personally guide you through a series of exercises designed to empower you with a deep understanding of React Server Components and the power of TypeScript. Discover how to optimize your applications, improve performance, and unlock new possibilities.
 
During the workshop, you will:
- Maximize code maintainability and scalability with advanced TypeScript practices
- Unleash the performance benefits of React Server Components, surpassing traditional approaches
- Turbocharge your TypeScript with the power of Mapped Types
- Make your TypeScript types more secure with Opaque Types
- Explore the power of Template Literal Types when using Mapped Types
 
Maurice will virtually be by your side, offering comprehensive guidance and answering your questions as you navigate each exercise. By the end of the workshop, you'll have mastered React Server Components, armed with a newfound arsenal of TypeScript knowledge to supercharge your React applications.
 
Don't miss this opportunity to elevate your React expertise to new heights. Join our workshop and unlock the potential of React Server Components with TypeScript. Your apps will thank you.