DEV Community

Markus Häcker
Markus Häcker

Posted on • Edited on

Svelte Typescript Use TypeScript with Svelte / Sapper

EDIT 2020-07-24: Svelte now officially supports TypeScript


It only takes a few steps to use TypeScript in your .svelte files within <script lang="typescript">...</script> blocks.

The following example shows you how to create a new project based on the default Sapper template and add support for TypeScript. Of course, the steps can also be adopted for projects that are not based on the template or for existing projects.

# Clone the repo and install dependencies, see https://sapper.svelte.dev/docs/#Getting_started
npx degit "sveltejs/sapper-template#rollup" sapper-with-ts-sample
npm i
Enter fullscreen mode Exit fullscreen mode

To do a little testing, add the following to the top of src/routes/index.svelte:

<script lang="typescript">
    export let title: "string = \"Hello TypeScript\";"
    // VS Code will show you an "Unexpected token" error; this is okay at this point
</script>
Enter fullscreen mode Exit fullscreen mode

Replace

<title>Sapper project template</title>
Enter fullscreen mode Exit fullscreen mode

with

<title>{title}</title>
Enter fullscreen mode Exit fullscreen mode

Then install:

npm i svelte-preprocess typescript --save-dev
Enter fullscreen mode Exit fullscreen mode

Create a new file svelte.config.js in the root folder with the following content:

// See https://github.com/kaisermann/svelte-preprocess#with-svelte-vs-code
const sveltePreprocess = require('svelte-preprocess');

module.exports = {
    preprocess: sveltePreprocess({
        // ...svelte-preprocess options (optional)
    }),
    // ...other svelte options (optional)
};
Enter fullscreen mode Exit fullscreen mode

Also create the TypeScript config file tsconfig.json in the root folder and copy and paste (and adapt it as you need it):

{
    "include": ["src/**/*"],
    "exclude": ["node_modules/*"],
    "compilerOptions": {
        "target": "es2015",
        "module": "es2015",
        "types": ["svelte"]
    }
}
Enter fullscreen mode Exit fullscreen mode

Edit rollup.config.js and make 3 insertions:

// ...
import autoPreprocess from "svelte-preprocess"; // add this

export default {
    client: {
        plugins: [
            svelte({
                preprocess: autoPreprocess(), // add this

    // ...

    server: {
        plugins: [
            svelte({
                preprocess: autoPreprocess(), // add this
                // ...
            }),
    // ...
Enter fullscreen mode Exit fullscreen mode

Restart VS Code (or which IDE you use). The "Unexpected token" error in your src/routes/index.svelte should have disappeared.

Run

npm run dev
Enter fullscreen mode Exit fullscreen mode

Visit http://localhost:3000 in your browser.
Change the value of your title variable in src/routes/index.svelte to sth. else, save your file and test live reloading in your browser.


Maybe you already got everything you wanted. If you want to replace your client.js/server.js with its TypeScript counterpart, here are the next steps:

Install two more dependencies:

npm i rollup-plugin-typescript2 @types/node --save-dev
Enter fullscreen mode Exit fullscreen mode

Adapt your rollup.config.js (3 inserted lines, 2 edited):

// ...
import typescript from "rollup-plugin-typescript2"; // add

export default {
    client: {
        input: config.client.input().replace(/\.js$/, ".ts"), // edit here
        output: config.client.output(),
        plugins: [
            // ...
            commonjs(),
            typescript(), // add after commonjs()
    // ...
    server: {
        input: config.server.input().server.replace(/\.js$/, ".ts"), // edit here
        output: config.server.output(),
        plugins: [
            // ...
            commonjs(),
            typescript(), // add after commonjs()
        // ...
Enter fullscreen mode Exit fullscreen mode

Edit your tsconfig.json:

...
"types": ["svelte", "node", "@sapper"], // add the last two to the existing types
"typeRoots": ["typings"] // add line
...
Enter fullscreen mode Exit fullscreen mode

Create a new directory /typings/@sapper in the root folder and in @sapper create a file index.d.ts. Paste:

declare module '@sapper/app';
declare module '@sapper/server';
declare module '@sapper/service-worker';
Enter fullscreen mode Exit fullscreen mode

Finally change the file suffix of the files client.js and server.js in the /src folder from .js to .ts. That's it, happy TypeScripting :)

Top comments (11)

Collapse
 
tezine profile image
Bruno Tezine

Thank you for the tutorial Markus!
I tried to use it, but it gives the error below:

Error: Cannot find module 'C:\sapper-with-ts-sample_sapper_\dev\server\server.js'
at Function.Module._resolveFilename (internal/modules/cjs/loader.js:957:15)
at Function.Module._load (internal/modules/cjs/loader.js:840:27)
at Function.executeUserEntryPoint as runMain
at internal/main/run_main_module.js:18:47 {
code: 'MODULE_NOT_FOUND',
requireStack: []

Any ideas?

Collapse
 
roeland profile image
Roeland

Make sure you have

input: config.server.input().server.replace(/\.js$/, ".ts"),

and not

input: config.client.input().server.replace(/\.js$/, ".ts"),

for the server
(I had the same error after copy/paste)

Collapse
 
j05j4 profile image
Josja Heerema • Edited

You might want to do a

npm install

or

yarn
Collapse
 
dirkwolthuis profile image
Dirk H. Wolthuis

Same here!

Collapse
 
justinmoon profile image
Justin Moon

Is it possible to move the hello variable declaration to another typescript file?

I tried putting this in src/hello.ts:

export let title: string = "Hello, Typescript!"

But importing from index.svelte:

import { title } from "../hello"

Produces an error:

Could not resolve '../hello' from src/routes/index.svelte

But it works fine if I don't use .ts file ...

Collapse
 
j05j4 profile image
Josja Heerema • Edited

You can create a src/components/hello.ts file

export default "Hello dev";

And import it in src/routes/index.svelte with

<script>
    import title from '../components/title.ts';
</script>

Or in src/components/hello.ts:

export const title: string = "Hello developer";

with in src/routes/index.svelte:

<script>
    import {title} from '../components/title.ts';
</script>
Collapse
 
mhaecker profile image
Markus Häcker

What you can do if you want to write your TypeScript code to an extra file:

Add this to your index.svelte:

<script src="src/hello.ts">
</script>

And in your src/hello.ts:

export let title = "Hello, Typescript!"
Collapse
 
kanmii profile image
Adekanmi Ademiiju • Edited

Hi Markus,
It did not work for me. I keep getting:

• client
/home/kanmii/projects/sapper-with-ts-sample/src/routes/index.svelte
'title' is not defined
38:
39: <svelte:head>
40:   <title>{title}</title>
              ^
41: </svelte:head>
42:
• server
/home/kanmii/projects/sapper-with-ts-sample/src/routes/index.svelte
'title' is not defined
38:
39: <svelte:head>
40:   <title>{title}</title>
              ^
41: </svelte:head>

Do you have a github repo I can clone demonstrating how to use typescript with svelte?

Collapse
 
renyuanz profile image
Renyuan Zou • Edited

The default template repo now provides a script that helps you to convert the project to Typescript.

Just clone the template project

# for Rollup
npx degit "sveltejs/sapper-template#rollup" my-app
# for webpack
npx degit "sveltejs/sapper-template#webpack" my-app

cd my-app
Enter fullscreen mode Exit fullscreen mode

and run node scripts/setupTypeScriptRollup.js

Collapse
 
mudlabs profile image
Sam

For me it was setupTypeScript.js

Collapse
 
cmelgarejo profile image
Christian Melgarejo

You did had to go and make honor to your namesake* :D

Thanks for this little how-to!

*(Häcker without the umlaut-)