Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you import a Svelte component in a Typescript file?

Is it possible to import a Svelte component in a Typescript file and have Rollup successfully compile it?

The following code works as a Javascript file, but errors when converted to Typescript, because the TS compiler doesn’t know how to handle a .svelte file:

import Component from './Component.svelte';

const foo = () => new Component({ target: document.body });

Is there a combination of rollup-plugin-svelte and @rollup/plugin-typescript that will preprocess the Svelte component in such a way that the Typescript compiler can include the Svelte code?


In case some more context is helpful, boardgame.io includes an in-browser debugging component built with Svelte, which is bundled in both a plain JS client & in a React client component, and we’re trying to update our Rollup config for exactly this scenario.

like image 985
delucis Avatar asked Jul 06 '20 17:07

delucis


People also ask

How do I import TypeScript into svelte?

Once you have TypeScript configured, you can start using it from a Svelte component by just adding a <script lang='ts'> at the beginning of the script section. To use it from regular JavaScript files, just change the file extension from . js to . ts .

Is svelte JavaScript or TypeScript?

Svelte is an emerging framework for building out front-end components with JavaScript, HTML, and CSS. It's pretty cool on its own, but it's made even more powerful with TypeScript.


2 Answers

Just to expand on Rich's answer, I was curious to investigate why importing Svelte helped in some setups.

the TS compiler doesn’t know how to handle a .svelte file

Svelte solves this (at least in the version at the time of writing, 3.35.0) by distributing a file in svelte/types/runtime/ambient.d.ts:

declare module '*.svelte' {
    export { SvelteComponentDev as default } from 'svelte/internal';
}

This effectively makes the TS compiler analyse .svelte files. Out of academic interest, it also declares the typings for all the runtime functionality that a script in a .svelte file has access to, such as set_attributes() (see svelte/internal for more). So just writing declare module '*.svelte' {} would only get you part of the way, as you'd also need those runtime declarations.

So, to get the TypeScript compiler to handle .svelte files, you need to – one way or another – reference the types of that file, svelte/types/runtime/ambient.d.ts. It's actually referenced indirectly by the package's entrypoint typings file (the value specified in the types field of Svelte's package.json), types/runtime/index.d.ts, so equally, you could reference that entrypoint typings file. Doing so would be best practice, as it would be robust against future refactors in the directory structure.

Extending @tsconfig/svelte/tsconfig.json satisfies this because the tsconfig file in question references the "svelte" node module through its compilerOptions.types property:

{
  // ... Omitted...

  "compilerOptions": {
    // ... Omitted...

    "types": ["svelte"]
  }
}

This effectively means that the compilation context will include this reference:

/// <reference types="svelte" />

You could equally write that same line yourself, though you might as well extend the Svelte tsconfig, as it would be robust to future Svelte evolution.

The suggestion of importing for side-effects works for the same reason:

import "svelte";

I found that even though I was extending the Svelte tsconfig, the Svelte types weren't being referenced. This turned out to be because I'd ended up with this line in my tsconfig:

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

  "compilerOptions": {
    // ... Omitted...

    "types": ["node"] // This overrides ["svelte"]!
  }
}

I fixed it by replacing "types": ["node"] with "types": ["node", "svelte"].

like image 83
Jamie Birch Avatar answered Oct 27 '22 21:10

Jamie Birch


Try adding @tsconfig/svelte to your project, then updating your tsconfig.json file:

{
  "extends": "@tsconfig/svelte/tsconfig.json",
  "include": ["src/**/*"],
  "exclude": ["node_modules/*", "__sapper__/*", "public/*"],
}
like image 35
Rich Harris Avatar answered Oct 27 '22 21:10

Rich Harris