#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)

green depot
#

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.

#

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'.

eternal karma
#

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?

green depot
#

@eternal karma I'm unsure what declare... incantation to use.

eternal karma
#

Or declare it as a global, rather

#
import type Quill from "quill"

declare global {
  var quill: Quill
}
green depot
#

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

eternal karma
#

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

green depot
#

no dice; I still get the TS1361 error for new Quill(...)

#

hang on, I'll make a StackBlitz

eternal karma
#

You may need to do the declare global in a different file than the new Quill

#

Here's a version that compiles at least:

void basaltBOT
#
retsam19#0

Preview:```ts
import type {
default as QuillType,
QuillOptions,
} from "quill"

declare global {
var Quill: typeof QuillType
}

const example = new Quill("body")```

green depot
#

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

eternal karma
#

var quill: InstanceType<typeof Quill> | null = null;

green depot
#

does that go inside the declare global - or in my top-level var quill:... line?

eternal karma
#

Or actually just var quill: QuillType | null = null; looks like it works too

#

Your var quill

green depot
#

hmm, yes, lemme do that locally

eternal karma
#

typeof Quill would be the constructor, you'd want the instance type.

green depot
#

hmm, problem:

#

my output .js file (from tsc) has an export { }: at the very bottom - I don't know where that is coming from

eternal karma
#

Yeah, if you've got any imports or exports in a file it becomes a module

green depot
#

I only have import type - no import statements

eternal karma
#

Yeah, still counts.

green depot
#

no, the documentation says otherwise

eternal karma
#

Type imports are removed at runtime, but the file is still considered a non-script.

pliant void
#

definitely does, i just tested

green depot
#

ugghghhhh

pliant void
#

you can do type Foo = import('blah').Foo to avoid that. it's ugly, but same functionality

green depot
#

why does typescript hate me so much?

eternal karma
#

Because you're using it in an archaic and non-standard way.

green depot
#

...how else are you meant to use TypeScript in a module-less application?

eternal karma
#

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.

green depot
#

...is import() "special" in TypeScript? or what does the output .js contain if I use it?

pliant void
#

if you use it in type-space like that then nothing

green depot
#

hmm, sec

pliant void
#

type Quill = typeof import("quill") gets entirely erased from the emit

green depot
#

okay, that's a start - but how do I use the QuillOptions and Toolbar types?

eternal karma
#
type Quill = typeof import("quill");
type QuillOptions = import("quill").QuillOptions;
type Toolbar = typeof import("quill/modules/toolbar");
green depot
#

...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.

void basaltBOT
#
retsam19#0

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");
...```

eternal karma
#

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.

green depot
#

@eternal karma oooh, that gets me down to 1 last error - about Toolbar

eternal karma
#

Yeah same issue there:

type ToolbarCtor = typeof import("quill/modules/toolbar").default;
declare var Toolbar: ToolbarCtor
let myToolbar = new Toolbar(quill, {})
green depot
#

if this works, how do I buy you a beer/coffee/etc?

eternal karma
#

No need, I'm here because I'm bored, but I appreciate the sentiment

green depot
#

one moment

eternal karma
#

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.

green depot
#

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;
eternal karma
#

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;
green depot
#

YESSSS

#

it builds!

#

thankyouthankyouthankyou

eternal karma
#

TIL there's a global browser variable called toolbar.

green depot
#

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?

eternal karma
eternal karma
green depot
#

!close