Svelte and TypeScript - Together at last!
Originally posted on the Scott Logic blog
Svelte is an up-and-coming web framework which removes the need for any runtime libraries by adding a transpilation step in its build process. I first started using Svelte in January, seen in my optimisation blog post, and have since used it for my AI music generation tool MuseTree. In my experience, Svelte was blazing-fast and super simple to use, making me more productive than ever before. There was just one problem:
no TypeScript support 😱
Thankfully, support has slowly been improving over time. You can see this evolution in MuseTree, with more and more of its code slowly becoming TypeScript as wider support was implemented. It has finally reached the point where I feel comfortable saying that you can use Svelte with TypeScript, so it's time to spread the word.
Get excited because we're about to use my two favourite web technologies together. Find a spare 5 minutes and grab your nearest Svelte project (store-bought is fine) - it's time to get stuck in.
All code samples in this post are taken from my example repo on GitHub
Update Your Build Config
These steps assume that you are starting with the official Svelte template
package.json
All that's changed in package.json
is some new dev dependencies:
svelte-preprocess
lets us define preprocessing steps in rollup@rollup/plugin-typescript
registers TypeScript transpilation as one of those stepstypescript
is used by the TypeScript pluginsvelte-check
gives us compile-time type checking
You can install all of these at once with
npm i -D svelte-preprocess @rollup/plugin-typescript typescript svelte-check
then follow it up with npm install
to make sure all your dependencies are installed.
rollup.config.js
This is where the real changes happen.
First, update the input
from main.js
to main.ts
.
Then import our two new plugins at the top of the file:
Next, we need to write our own plugin, as seen below.
This plugin runs svelte-check
, which is a command-line utility and not available as a rollup plugin directly.
Add this block to the bottom of your rollup config.
Finally, at the top of the plugins list, add this block to register the three new plugins:
If you already have a svelte
section in your config, just replace it.
Now, every time we build our project, it will first type-check your code and transpile any TypeScript code into JavaScript.
tsconfig.json
Since we're using TypeScript, we need a tsconfig.json
file to configure it.
Nothing special here, so if you're experienced with TypeScript then use it like normal.
Otherwise, just create a file at the root of your project named tsconfig.json
containing this config:
main.js
Rename your entrypoint from main.js
to main.ts
.**
The first line, import App from './App.svelte';
will cause compilation errors as you can't import a Svelte component into a TypeScript file.
Make the compiler ignore that error by adding // @ts-ignore
on the line above the import.
That's everything! Your Svelte project is now configured to work with TypeScript.
Start Using TypeScript in Svelte
First things first, use an IDE that supports the Language Server Protocol. That includes VS Code, Atom, Sublime Text, and many others. It does not include JetBrains IDEs. Even as a die-hard JetBrains fan, I have resigned myself to using VS Code, which is the best supported. A full list of supported IDEs is available here.
Get the relevant Svelte extension - such as Svelte for VS Code. This adds in-IDE type checks for your Svelte code.
Then simply change your <script>
tag to <script lang="ts">
in each Svelte component, and you're off!
Start using TypeScript, and you'll see any type errors in your IDE.
When you're running the project, you'll also get type errors in the terminal:
Gotchas
The TypeScript support in Svelte isn't perfect. There's a few things you need to look out for:
- When importing a type into a Svelte component, you need to use the
import type
syntax. This means you might have two import statements for one file, like this:
- To add types to a reactive declaration (
$:
), you have to do it in two steps. First, declare the variable using let with the correct type. Then add a reactive declaration like normal, without any types.
- The type definitions for the inline
style
on a DOM component are lying. They say they support JSX-like style objects, but really only support strings. If you want to use JSX, try thereact-style-object-to-css
library. - Types are only checked inside the
<script>
tags, meaning you can have a text input withbind:value={stringVariable}
. - The app won't live-reload when you change a
.ts
file, only when you change the.svelte
files.
Conclusion
Svelte is amazing, and it's even better with TypeScript. While support isn't perfect, it's good enough that I'd recommend it to anyone that's used Svelte and TypeScript before. If you've been waiting for TypeScript support before learning Svelte, now's the time to get stuck in.
Make sure you check out the GitHub Repo which contains a working example project.