Making Magic: Building a TypeScript-First Framework

Rate this content
Bookmark

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.

This talk has been presented at TypeScript Congress 2023, check out the latest edition of this JavaScript Conference.

FAQ

Nuxt is a progressive framework built on Vue.js for building web applications. It incorporates Vue as the rendering layer and includes a server engine called Nitro. Nuxt focuses on providing a developer-friendly experience with built-in best practices and easy configurability.

TypeScript is utilized in Nuxt to provide a more robust and native experience, aiming to reduce friction and distraction for developers. By making Nuxt TypeScript-native, the framework can offer better inference, augmentation, and expose more project truths to developers, enhancing type safety and developer productivity.

Nuxt aims to be the source of truth in a project, facilitating better TypeScript integration. This includes generating a tsConfig that reflects the true configuration of the project and improving type inference and augmentation to support extensive customization and extensibility through modules.

Yes, Nuxt modules can add their own templates and asynchronously define type templates at runtime. This allows module authors to control and customize the types and type environments within a Nuxt project, enhancing flexibility and extensibility.

Nuxt enhances type safety by managing server endpoints and fetch functions within the project, allowing it to provide types automatically. This integration simplifies the process for developers, ensuring that API interactions are type-safe without requiring additional coding from the user.

In Nuxt, tsConfig plays a crucial role by reflecting the accurate project settings and paths as defined in the Nuxt configuration. This setup helps maintain consistency and ensures that the TypeScript compiler understands the project structure correctly, aiding in better development practices.

Nuxt uses RuntimeConfig to manage environment variables, ensuring they are type-safe and can be overridden at runtime if needed. This approach allows developers to access and use environment variables securely and efficiently within their applications.

Daniel Roe
Daniel Roe
31 min
21 Sep, 2023

Comments

Sign in or register to post your comment.

Video Summary and Transcription

Daniel Rowe discusses building a TypeScript-first framework at TypeScript Congress and shares his involvement in various projects. Nuxt is a progressive framework built on Vue.js, aiming to reduce friction and distraction for developers. It leverages TypeScript for inference and aims to be the source of truth for projects. Nuxt provides type safety and extensibility through integration with TypeScript. Migrating to TypeScript offers long-term maintenance benefits and can uncover hidden bugs. Nuxt focuses on improving existing tools and finds inspiration in frameworks like TRPC.

1. Introduction and Background

Short description:

Daniel Rowe, NUXT maintainer and open-source library author, discusses building a TypeScript-first framework at TypeScript Congress. He shares his involvement in various projects, such as Fontane, Magic Regular Expressions, and Elk. Daniel invites the audience to connect with him on his website at roe.dev and offers assistance with questions, help, and open source contributions. He also mentions his location in the UK and the unpredictable weather.

How TypeScript Works Hello. It's a real pleasure to be here at TypeScript Congress talking about making magic, building a TypeScript-first framework. My name is Daniel Rowe. I'm an open-source library author and maintainer of NUXT, which is a framework for building web applications. I'm also involved in some other things from Fontane, which helps reduce cumulative layout shift with custom web fonts, to Magic Regular Expressions, which is a re-imagination of what projects could be like, based heavily on TypeScript magic, to Elk, which is a client for Mastodon, a distributed social network. I'm also a Google GDE and a Microsoft MVP. You can get in touch with me on my website at roe.dev. If there's anything that I can help you with, I would love to. I'm accessible if you have questions, or you need help, or you want to contribute to open source. For whatever reason, it would be really nice to say hi. I live in the UK, in the northeast of England, in a lovely rural setting, by the banks of a river, in the shadow of an ancient forest. I have three cats and a dog, and this is where I am right now. And probably, when you get in contact or send me a message, you'll find me in this exact kind of situation. It's been raining a little bit today, but it's also sunny. So that's a pretty good indication of UK weather, if you're not familiar with it.

2. Nuxt Framework and TypeScript Integration

Short description:

Nuxt is a progressive framework built on Vue.js, providing a seamless developer experience with best practices and configurability. The goal is to reduce friction and distraction, allowing developers to focus on their code. The use of TypeScript at a core level aims to enhance this experience, with a focus on being the source of truth, leveraging inference, enabling augmentation, and revealing project truth to the end user.

And you're probably wondering what is Nuxt, if you haven't come across it before. It's a progressive framework built on Vue.js. Vue is the rendering layer for the front end, but it's full stack. So it also has a server engine called Nitro, which is now a framework of its own and used by other meta-frameworks as well.

One of the key things for Nuxt is the developer experience. So it's all about making something that is easy to use, that has best practices built in, but doesn't impose a high barrier to entry, but at the same time is configurable and allows you to extend it as you need, as you grow and have different requirements, it should grow with you.

A few years ago, we started to rebuild Nuxt. And one of the things that we worked on that we wanted to do was think about how we could make Nuxt even more magical. And I think magic is a really important characteristic of a framework that I would want to use. I know sometimes it can be used in a pejorative sense, but I think magic is something that we want in terms of developer experience. And for me, it's really these two qualities. It's about reducing friction, keeping you in a single context, and about reducing distraction. So, adopting a more minimalistic principle.

So, wherever you switch context, if you're a developer and you're writing code, ideas are flowing through you and out, if there's something that stops you from that, whether that's you have to go to the documentation to find out something, or you need to check in another part of your project to understand whether you can do what you're trying to do, that is going to slow you down and create a feeling of frustration. And the same is true, I think, with distraction. So, when you find yourself having to maintain complex bundler configuration or to repeat code over and over again, even when you open a new component and you see 20 lines of imports at the top before you even see the code that you want to look at, all of that, I think, can get in the way of flow, state, something that makes you feel productive and to enjoy and flourish in what you're doing. And so I think magic is one of the things that we can do, can provide us framework offers that can dramatically improve the experience of developers.

So, when we came, as I was saying, to rebuild Nuxt from the ground up, for us, it was about thinking, how can we use TypeScript to make this kind of magic? Because building the framework, writing it in TypeScript is pretty much table stakes. But what could we do if we aimed to have TypeScript built in at a much more core level for the framework itself to be TypeScript native? And I came up with these four different possibilities, and you might have others, and more might go to me later. But I thought these would be helpful guide to go through. And the first is that it has to be designed to be the source of truth in a project. The framework needs to be designed for inference, so it takes best advantage of TypeScript to do what it can do. It needs to be designed for augmentation. And it needs to be designed to reveal all of the truth of the project as much as possible to the end user. So, what do I mean? First, designed as a source of truth. So, the moment you clone a new project in any framework, often you'll find that there's a page in the documentation called using with TypeScript. And in this page, there's then a tsConfig. And you can go to the page and copy and paste it into your project. Or maybe you have a template where it's already there. And from that moment on, your TypeScript config starts to diverge from the reality of the library.

QnA