#Getting SVG.js to work in typescript

1 messages · Page 1 of 1 (latest)

jolly sable
#

Hello,

I'm making this post for what seems to be a rather simple question, but I've already spent the best part of a day trying to figure this out. I'm simply trying to create a TypeScript project that uses SVG.js (https://svgjs.dev/docs/3.0/). My project code will all run in the browser. My project structure looks something like this (excluding node_modules):

.
├── dist
│   ├── index.js
│   └── index.js.map
├── package.json
├── package-lock.json
├── src
│   ├── index.html
│   └── index.ts
└── tsconfig.json

I've installed SVG.js as described in the official docs:
npm install @svgdotjs/svg.js

And then I try to import it as follows (again, as described in the official docs):
import { SVG } from '@svgdotjs/svg.js'

However I can't get this to work. Either I get errors with typescript like the following:
1. Cannot find module '@svgdotjs/svg.js'. Did you mean to set the 'moduleResolution' option to 'nodenext', or to add aliases to the 'paths' option?
or typescript can't seem to find attributes of my imported class.

Even when I manage to get it to compile by tweaking the tsconfig.json, I get errors in the browser like:
Uncaught SyntaxError: export declarations may only appear at top level of a module or
Uncaught TypeError: The specifier “@svgdotjs/svg.js” was a bare specifier, but was not remapped to anything. Relative module specifiers must start with “./”, “../” or “/”. index.js:1:21

So now I'm a bit lost, I was wondering if anyone knows of a right way of doing this. Thank you.

stable hawk
jolly sable
#

no I'm not, should I?

stable hawk
#

depends on your preference, i guess

#

you can't just import @svgdotjs/svg.js from the browser, the browser doesn't know what that is.
you have these options:

  • define an import map
  • import from the cdn url, such as https://cdnjs.cloudflare.com/ajax/libs/svg.js/3.2.4/svg.esm.min.js, and define types for that
  • import as a script globally, then declare global its existance
  • use a bundler or build system that works on node, and from there you can import from @svgdotjs/svg.js
#

(and for the last option, you have more choices as to what tool you want to use to achieve that)

jolly sable
#

Okay I'll look into the first option. And just out of curiosity why can't I do something like ../node_modules/@svgdotjs/svg.js, since I've noticed this doesn't work.

Also is there one option you recommend over the others? Like will the lsp find autocomplete with all of these options?

stable hawk
#

Like will the lsp find autocomplete with all of these options?
i'm not sure for the import map, ive never touched that personally, but yes for the others
Also is there one option you recommend over the others?
i'd recommend server-side (last option), it yields more flexibility, but of course at the cost of added complexity

#

And just out of curiosity why can't I do something like ../node_modules/@svgdotjs/svg.js, since I've noticed this doesn't work.
because once you're in the browser, you only have access to stuff you're serving. each import is a request, working on the server with slugs, not on the filesystem with paths (unless you're just opening the html file directly)

jolly sable
#

ah yes makes sense. thank you so much for your help, I'll look into the things you've told me and update here if I get it to work :)

jolly sable
#

Hello again, I'm now using webpack but I still can't get it to work.

When I run the code I now get an error:

Uncaught ReferenceError: can't access lexical declaration 'Ue' before initialization
    r make namespace object:3
    <anonymous> bundle.js:1
    <anonymous> bundle.js:1
make namespace object:3:11

I don't really know where to go from here. I'm attaching my tsconfig.json and webpack-config.js in case that helps. And to be clear I'm still importing with: import { SVG } from '@svgdotjs/svg.js'

#

Oh also I know the error comes from importing SVG.js because when I don't I don't get the error.

#

Looks like changing module to commonjs and removing the verbatimModuleSyntax option solved it. Thanks again for the help

#

!resolved

stable hawk
#

oh if you're using a bundler you should probably use moduleResolution: bundler

jolly sable
#

oh damn, I'll try that too.

stable hawk
#

sorry, wrong flag, edited

jolly sable
#

huh I now get: ERROR
TS5095: Option 'bundler' can only be used when 'module' is set to 'preserv
e' or to 'es2015' or later.

#

yeah I have absolutely no idea why, but if I change moduleResolution: bundler it tells me I have to use es2015, but when I do that the website breaks again

stable hawk
#

yeah doesn't work with cjs i think?

#

you can use esnext or preserve, not sure which would be better for a bundler

#

i'd guess preserve?

jolly sable
#

I'll try that too

#

especially since now commonjs and node are breaking too

#

when I use import '@svgdotjs/svg.draggable.js'

#

whcih is a plugin to SVG.js

#

using
moduleResolution: bundler
and module: preserve

makes me unable to do circle.draggable() which should be made available through the draggable plugin

#

this is starting to frustrate me

stable hawk
#

what about esnext?

jolly sable
#

same thing; TS2339: Property 'draggable' does not exist on type 'Circle'.

#

!unresolve

hexed marsh
#

What is circle and where is it coming from?

jolly sable
#

it's a class provided by SVG.js

hexed marsh
#

Hmm works on the TS playground without any special configuration

willow trenchBOT
#
retsam19#0

Preview:```ts
import Svg from "@svgdotjs/svg.js"
import "@svgdotjs/svg.draggable.js"

const circle = new Svg.Circle()
circle.draggable()```

hexed marsh
#

And the TS types are built into the package so you shouldn't have to do anything special with installation

#

Do you have an explicit import "@svgdotjs/svg.draggable.js" in your code?

#

(Also if you're just picking up a bundler for this project, would recommend vite over webpack though it shouldn't really matter for this one)

jolly sable
hexed marsh
jolly sable
#

yes

#

it seems like the issue is arising when bundling svg.draggable.js

#

because the error I get in my browser points me to a file called svg.draggable.js under webpack

hexed marsh
#

If you're getting a typescript error and a browser error those are two separate things

#

TS doesn't exist at runtime

jolly sable
#

I'm getting a browser error now

#

but it depends on how i configure my tsconfig.json

#

either I get the error: TS2339: Property 'draggable' does not exist on type 'Circle'. in typescript or I get an error:

Uncaught TypeError: t is undefined
    r svg.draggable.js:10
    183 svg.draggable.js:1
    Webpack 4
svg.draggable.js:10:1507

in my browser

#

another update. Just using:

<script src="https://cdn.jsdelivr.net/npm/@svgdotjs/[email protected]/dist/svg.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@svgdotjs/[email protected]/dist/svg.draggable.min.js"></script>

to import the libraries works just fine, confirming the issue is with the bundling process. The problem is that if I import them as shown above I get no autocomplete, in fact I get a bunch of TS errors.

hexed marsh
#

Yeah, if you import things via scripts, TS won't know about it.

jolly sable
#

no way around that? I don't really care about bundling for now, the only reason I do so was to resolve the issue

stable hawk
#

you could declare global it

hexed marsh
#

I do think probably an import map is the easiest vanilla, non-bundled option.