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.
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 .
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.
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"]
.
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/*"],
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With