Svelte/Typescript error : "unexpected token" during type declaration
Asked Answered
S

5

8

So I have a Svelte application with TypeScript enabled but now I am having an issue for running it :

[!] Error: Unexpected token (Note that you need plugins to import files that are not JavaScript)
src\api.ts (4:7)
2:
3: export default class API {
4:     url:string;
          ^
5:

I don't understand because the app was working before, and suddenly raised this error. It seems that some versions related to TypeScript for Svelte was changed:

{
  "name": "...",
  "version": "...",
  "private": ...,
  "scripts": {
    "build": "rollup -c",
    "dev": "rollup -c -w",
    "start": "sirv public --no-clear",
    "validate": "svelte-check",
    "check": "svelte-check --tsconfig ./tsconfig.json"  /* + ADDED */
  },
  "devDependencies": {
    "@rollup/plugin-commonjs": "...",
    "@rollup/plugin-json": "...",
    "@rollup/plugin-node-resolve": "^13.1.3",
    "@rollup/plugin-typescript": "^8.0.0",
    /* @smui/... stuffs */
    "@tsconfig/svelte": "^2.0.0",     /* ^1.0.0 -> ^2.0.0 */
    "rollup": "^2.67.0",
    "rollup-plugin-css-only": "^3.1.0",
    "rollup-plugin-livereload": "^2.0.5",
    "rollup-plugin-svelte": "^7.1.0",
    "rollup-plugin-terser": "^7.0.2",
    "svelte": "^3.46.3",
    "svelte-check": "^2.0.0",         /* ^1.0.0 -> ^2.0.0 */
    "svelte-preprocess": "^4.0.0",
    "tslib": "^2.0.0",
    "typescript": "^4.0.0"
  },
  "dependencies": {
    "sirv-cli": "^2.0.2",
    "svelte-material-ui": "..."
  }
}
/* Note: I replaced some unrelated properties/version by '...'. */

Of course executing npm install didn't help. And if I just remove the :string, it will throw the same error for all other :<type> in the code.

Note that the file is named .ts and that VSCode doesn't detect any syntax error in those files.

Config files (edit)

/* tsconfig.json */
{
  "extends": "@tsconfig/svelte/tsconfig.json",

  "include": ["src/**/*"],
  "exclude": ["node_modules/*", "__sapper__/*", "public/*"]
}
/* rollup.config.js */
import svelte from 'rollup-plugin-svelte';
import commonjs from '@rollup/plugin-commonjs';
import json from '@rollup/plugin-json';
import resolve from '@rollup/plugin-node-resolve';
import livereload from 'rollup-plugin-livereload';
import { terser } from 'rollup-plugin-terser';
import sveltePreprocess from 'svelte-preprocess';
import typescript from '@rollup/plugin-typescript';
import css from 'rollup-plugin-css-only';

const production = !process.env.ROLLUP_WATCH;

function serve() {
    let server;

    function toExit() {
        if (server) server.kill(0);
    }

    return {
        writeBundle() {
            if (server) return;
            server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], {
                stdio: ['ignore', 'inherit', 'inherit'],
                shell: true
            });

            process.on('SIGTERM', toExit);
            process.on('exit', toExit);
        }
    };
}

export default {
    input: 'src/main.ts',
    output: {
        sourcemap: true,
        format: 'iife',
        name: 'app',
        file: 'public/build/bundle.js'
    },
    plugins: [
        svelte({
            preprocess: sveltePreprocess({ sourceMap: !production }),
            compilerOptions: {
                dev: !production
            }
        }),
        css({ output: 'bundle.css' }),
        resolve({
            browser: true,
            dedupe: ['svelte']
        }),
        commonjs(),
        typescript({
            sourceMap: !production,
            inlineSources: !production
        }),
        json(),
        !production && serve(),
        !production && livereload('public'),
        production && terser()
    ],
    watch: {
        clearScreen: false
    }
};

No file svelte.config.js

Shandy answered 2/7, 2022 at 18:54 Comment(3)
seems like you need to add a plugin to import typescript files. This article could be useful. Looks like your question may have also been answered hereVentre
Show your other config files, in particular Rollup's, any tsconfig.json and the svelte.config.js, if there is one.Syzran
Thank you Ross and H.B. for your comments. @Ross, unfortunately I already followed this path and it didn't help. :(Shandy
S
0

So, I tried executing my app in a docker container, to see if it would work, and got a different error message, much more helpful:

[!] Error: Could not resolve './api.js' from src/App.js`

Indeed, the file is not named ./api.js but ./API.ts (forgot to change the import after renaming it to TS...)

So I changed the import like that:

/* Before (not working) */
import API from './api.js'
/* After (Good) */
import API from './API' 

// NB. The filename is really in uppercase for me

TL;DR

  • Check your import for any import x from file.js which should be a TS file and replace them by import x from file (you should not write the .ts extension)

Explanation:

It is trying to import a JavaScript (.js) file, but find the TypeScript file (.ts) and import it instead (seems like it only cares about the "basename"), but without the TypeScript Support, creating this weird situation where it doesn't reconize TypeScript Syntax inside a .ts file.

Shandy answered 2/7, 2022 at 19:49 Comment(0)
B
13

Having setup my project from the latest svelte template with Typescript enabled, faced a similar "unexpected token" complaint when trying to import types into .svelte files, not in the code editor but the server.

Fix was to explicitly set the preprocess option in svelte.config.js to vitePreprocess(). This was unexpected since the svelte docs (currently) state that this is included by default if Typescript is enabled during setup! https://kit.svelte.dev/docs/integrations#preprocessors

import { vitePreprocess } from '@sveltejs/kit/vite';
 
export default {
  preprocess: [vitePreprocess()]
};
Bozuwa answered 20/3, 2023 at 7:44 Comment(0)
E
4

For me, it seems I just had to specify the lang attribute in the <script> tag as "ts".

<script>
...
</script>

To

<script lang="ts">
...
</script>
Epigrammatist answered 2/8, 2023 at 18:34 Comment(2)
Important to make sure it's lang, not type or anything else. They look very similar, but type doesn't work here.Selfeffacement
Thanks @u32i64! I copied an error page template from SO and the tag was type. When viewing the file it looked correct and svelte marked the variable declaration as problematic, not the tag.Poulos
S
0

So, I tried executing my app in a docker container, to see if it would work, and got a different error message, much more helpful:

[!] Error: Could not resolve './api.js' from src/App.js`

Indeed, the file is not named ./api.js but ./API.ts (forgot to change the import after renaming it to TS...)

So I changed the import like that:

/* Before (not working) */
import API from './api.js'
/* After (Good) */
import API from './API' 

// NB. The filename is really in uppercase for me

TL;DR

  • Check your import for any import x from file.js which should be a TS file and replace them by import x from file (you should not write the .ts extension)

Explanation:

It is trying to import a JavaScript (.js) file, but find the TypeScript file (.ts) and import it instead (seems like it only cares about the "basename"), but without the TypeScript Support, creating this weird situation where it doesn't reconize TypeScript Syntax inside a .ts file.

Shandy answered 2/7, 2022 at 19:49 Comment(0)
K
0

For me it was, to clearly declare, that I use typescript not only generally but also within Svelte:

{
  "env": {
    "browser": true,
    "node": true,
    "es2021": true
  },
  "globals": {
    ...
  },
  "extends": [
    "standard",
    "plugin:svelte/recommended",
    "plugin:@typescript-eslint/recommended"
  ],
  "parser": "@typescript-eslint/parser",   // <-- you might say typescript here
  "parserOptions": {
    "sourceType": "module",
    "extraFileExtensions": [".svelte"]
  },
  "plugins": ["@typescript-eslint"],
  "overrides": [
    {
    "files": ["*.svelte"],
    "parser": "svelte-eslint-parser",
    "parserOptions": {
      "parser": "@typescript-eslint/parser" // <-- you HAVE TO say typescript here again
    }
    }
  ]
  }

See second code snippet in this section: https://github.com/sveltejs/eslint-plugin-svelte?tab=readme-ov-file#parser-configuration

Kurtkurth answered 13/1 at 13:36 Comment(0)
F
0

If you use both JS and TS in a project, this eslint config helps:

  overrides: [
     {
       files: ['*.svelte'],
       parser: 'svelte-eslint-parser',
       parserOptions: {
         parser: {
           // Specify a parser for each lang.
           ts: '@typescript-eslint/parser',
           js: 'espree',
           typescript: '@typescript-eslint/parser'
         }
       }
     }
   ],
Faus answered 23/1 at 14:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.