node.jstypescriptnpmsvelte

Svelte/Typescript error : "unexpected token" during type declaration


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


Solution

  • 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

    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.