I'm working on a good ol' fashioned SSR (ASP.NET Core) web-application; some of my pages have their own .ts files (which are Global TypeScript files: no import/export statements). I'm using quill in one page (with <script src="/scripts/quill/quill.js"> which is not an ECMAScript Module; this is the dist file from the npm package. I want to use the @types/quill typings, but the index.d.ts file has import/export statements, so TypeScript is forcing me to useimport Quill from "quill"; in my page-specific .ts file which means the TSC-generated output .js is also an ECMAScript module - but I don't want this. I tried using /// <reference path=".../node_modules/quill/etc..." but that fails because TS thinks it's a module.
#How do I use types from a @types without using `import`? I don't want a module file!
1 messages · Page 1 of 1 (latest)
I tried using import type - which looked promising at first, but doesn't work for me because my code calls new Quill() which fails:
(TS) 'q' cannot be used as a value because it was imported using 'import type'.
Yeah, doing actual global script files is somewhat tricky.
If you're expecting Quill to be attached directly to the window, I think you'd need to declare it that way?
@eternal karma I'm unsure what declare... incantation to use.
Or declare it as a global, rather
import type Quill from "quill"
declare global {
var quill: Quill
}
well, I actually have this:
import type { default as Quill, QuillOptions } from "quill";
import type Toolbar from "quill/modules/toolbar";
I don't know how to translate that into a declare global
I think it'd still be the same declare global above?
Or maybe with a capital Q, I don't know what global the quill script attaches
no dice; I still get the TS1361 error for new Quill(...)
hang on, I'll make a StackBlitz
You may need to do the declare global in a different file than the new Quill
Here's a version that compiles at least:
Preview:```ts
import type {
default as QuillType,
QuillOptions,
} from "quill"
declare global {
var Quill: typeof QuillType
}
const example = new Quill("body")```
You can choose specific lines to embed by selecting them before copying the link.
@eternal karma here: https://stackblitz.com/edit/vitejs-vite-ajg8ewkk?file=wwwroot%2FExamplePage.ts
uhh, I used stackblit'z TS vanilla template - I don't know why it says "Vite"
running tsc in the Stackblitz project root gives me the same TS1361 error I get locally
var quill: InstanceType<typeof Quill> | null = null;
does that go inside the declare global - or in my top-level var quill:... line?
Or actually just var quill: QuillType | null = null; looks like it works too
Your var quill
hmm, yes, lemme do that locally
typeof Quill would be the constructor, you'd want the instance type.
hmm, problem:
my output .js file (from tsc) has an export { }: at the very bottom - I don't know where that is coming from
Yeah, if you've got any imports or exports in a file it becomes a module
I only have import type - no import statements
Yeah, still counts.
Type imports are removed at runtime, but the file is still considered a non-script.
definitely does, i just tested
ugghghhhh
you can do type Foo = import('blah').Foo to avoid that. it's ugly, but same functionality
why does typescript hate me so much?
Because you're using it in an archaic and non-standard way.
...how else are you meant to use TypeScript in a module-less application?
Anyway, I think you may need to do type Quill = typeof import("quill") rather than ESM import syntax to keep it from being a module.
...is import() "special" in TypeScript? or what does the output .js contain if I use it?
if you use it in type-space like that then nothing
hmm, sec
type Quill = typeof import("quill") gets entirely erased from the emit
okay, that's a start - but how do I use the QuillOptions and Toolbar types?
type Quill = typeof import("quill");
type QuillOptions = import("quill").QuillOptions;
type Toolbar = typeof import("quill/modules/toolbar");
...huh, I didn't know you could do that
@eternal karma unfortunately that didn't work:
I've updated the stackblitz project
I'm getting this error for new Quill(...)
rror TS2693: 'Quill' only refers to a type, but is being used as a value here.
Preview:```ts
// The default export is the constructor
type QuillCtor = typeof import("quill").default
type Quill = InstanceType<QuillCtor>; // There may be a way to get this directly from an import
type QuillOptions = import("quill").QuillOptions;
type Toolbar = typeof import("quill/modules/toolbar");
...```
You can choose specific lines to embed by selecting them before copying the link.
Here's a form that seems to work. A lot of nuance between the type of the module itself and the type of the constructor and the type of an instance.
And you still need something to declare the global variable.
@eternal karma oooh, that gets me down to 1 last error - about Toolbar
Yeah same issue there:
type ToolbarCtor = typeof import("quill/modules/toolbar").default;
declare var Toolbar: ToolbarCtor
let myToolbar = new Toolbar(quill, {})
if this works, how do I buy you a beer/coffee/etc?
No need, I'm here because I'm bored, but I appreciate the sentiment
one moment
But yeah, raw non-module TS files aren't super fun - I know you can't always avoid legacy projects (and I don't have any specific experience with ASP.NET Core), but if there's some way to throw a layer in between your TS code and the code that runs so you can use modules that would definitely be nice.
ASP.NET Core behaves just the same as PHP or JSP - it's just plain ol' SSR HTML
hmm, still getting an error for my Toolbar declaration and usagfe
(TS) 'Toolbar' refers to a value, but is being used as a type here. Did you mean 'typeof Toolbar'?
that's for this:
const toolbar = quill.getModule('toolbar') as Toolbar;
This seems to work:
type ToolbarCtor = typeof import("quill/modules/toolbar").default;
type Toolbar = InstanceType<ToolbarCtor>
declare var Toolbar: ToolbarCtor
const myToolbar = quill.getModule('toolbar') as Toolbar;
TIL there's a global browser variable called toolbar.
yes, navigator.toolbar - I think that dates back to IE3 when they added the Win32 Rebar control to the browser shell
hmm, or not
oh, it's window.toolbar - not navigator.toolbar
how do I mark this thread as Resolved?
FWIW, you might still consider something like a bundler that produces each individual JS file - would let you write your code split into modules but still produce flat JS files at the end
You can send !close
at this point, let's just say that would be adding more trouble than it's worth
!close