Can TypeScript understand Svelte components?

Chris Talman picture Chris Talman · Jan 7, 2018 · Viewed 7.3k times · Source

Svelte ultimately outputs native JavaScript classes. So, TypeScript could understand these. However, Svelte components have to first be compiled from their initial .html form. Until then, understandably, TypeScript by default does not understand them in their initial form. So, it reports a 'cannot find module' error, even though at runtime the import is successful. Is there any way to make TypeScript understand them?

One workaround would be to provide type definitions for .html modules, approximating the standard Svelte component interface. However, it would be much more desirable to simply use the real component class output itself for each individual component, yielding the most accurate type information.

As an aside, I have not mentioned tools like Webpack or Rollup which perform the compilation step for Svelte normally. I do not know whether these tools would be relevant to this question.

Update 1: I've looked a little further into TypeScript and it seems that plugins can be created for it. However, they seem limited, so may not be useful.

Update 2: There has also been some talk (here and here) about custom module loaders in TypeScript.

Answer

Scott Willeke picture Scott Willeke · Jan 8, 2018

Yes. Use rollup-plugin-svelte and rollup-plugin-typescript and it should work. I am using it in a rollup file now that looks as follows:

import commonjs from 'rollup-plugin-commonjs'
import replace from 'rollup-plugin-replace'
import resolve from 'rollup-plugin-node-resolve'
import svelte from 'rollup-plugin-svelte'
import typescript from 'rollup-plugin-typescript'

const path = require('path')
const fs = require('fs')

export default {
  input: 'src/index.ts',
  plugins: [
    typescript(),
    commonjs({
      include: 'node_modules/**'
    }),
    resolve({
      browser: true,
      preferBuiltins: false // for url npm module; otherwise rollup assumes node
    }),
    // Replace is to shut up redux
    replace({
      'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV)
    }),
    svelte({
      // By default, all .html and .svelte files are compiled
      extensions: ['.my-custom-extension', '.html', '.svelte'],

      // You can restrict which files are compiled
      // using `include` and `exclude`
      // include: 'src/components/**/*.html',

      // By default, the client-side compiler is used. You
      // can also use the server-side rendering compiler
      // generate: 'ssr',

      // Extract CSS into a separate file (recommended).
      css: function (css) {
        fs.writeFileSync('./dist/svelte.css', css)
      }
    })
  ],
  output: {
    format: 'iife',
    file: path.join(__dirname, './dist/index_dist.js') // equivalent to --output
  }
}