-
-
Notifications
You must be signed in to change notification settings - Fork 393
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Bring back the uPlot typescript namespace #444
Comments
why not import uPlot, * as uType from "uplot";
const axis: uType.Axis = {...};
const plot = new uPlot(); |
I would still have two differently named references to the same package. |
can you check if this still plays nice with module augmentation: #441 (comment) |
I tested augmenting a class with a namespace here. Is this what you wanted to check? |
yeah, that looks like it works. is there any difference between any drawbacks to just using using namespaces in both places works too: https://www.typescriptlang.org/play?#code/CYUwxgNghgTiAEkoGdnwK4AUIHsAu8A3gFAC+xxoSc8AdlALYjIAOUYCWuBJ8f8AS1p4QMAGbsEAZVEDmRYvyXwoALngAjHDgggotRf3LlK4aDXpNWkjNnwKlQkeJsyYctL2V8N6rTr0DJWMKMBxaZAJkWWZ1LnwAOjcPeABeIhV1PBh0EAAaTSychFJ4AHoy+ABhfRUwDlR4PABPFnl9YBV0AHMmYSaACxAGUPDI+BZuNLoQAHdbbgAKAEpyypraRDHs9DACPCHEaFRiIA i guess https://www.typescriptlang.org/docs/handbook/namespaces-and-modules.html |
Yeah seems like you guessed right. |
want to PR this and i'll test how it drops into Grafana? |
I'm almost done with the commit here, but while I was going through the declaration file I found a problem unrelated to this issue I opened, just a observation: if you import the const enums that are in the declaration file it would seem ok in TS but would be Basically, if you do this: import uPlot, { DrawOrderKey } from 'uplot'
console.log(DrawOrderKey.Axes) TS assumes that the This has nothing to do with the namespace issue by the way |
i'm fairly certain this is an old babel-specific issue. see babel/babel#8741, grafana/grafana#29293. const enums are specifically there compile down to their values without overhead, and the real TS compiler does in fact do this. https://www.typescriptlang.org/docs/handbook/enums.html#const-enums demo: this looks like the "solution": https://github.com/dosentmatter/babel-plugin-const-enum |
But does TS compiles enums that are only in declaration files? From what I understand, you can't import "real" values from .d.ts files, so the uPlot source code would have to be written in TS I think. Also I'm using esbuild instead of babel, and when I tried to import some enum like |
that's a good question, and worth testing with a raw TS compiler.
right, but const enums are not "real" values. i would expect that the compiler would behave the same way for type-only transpilations regardless of where they come from, why shouldn't it? |
i tested it with these files in the same directory: uPlot.d.ts: export const enum Foo {
Bar = 1,
Moo = 2,
} test.ts: import { Foo } from './uPlot';
console.log(Foo.Bar); CLI (TypeScript 4.1.3):
output (test.js): "use strict";
exports.__esModule = true;
console.log(1 /* Bar */); |
That's good to know 🤔 $ esbuild --bundle test.ts
> test.ts: error: Could not resolve "./uPlot"
1 │ import { Foo } from './uPlot';
╵ ~~~~~~~~~ |
Using uPlot.d.ts: declare namespace uPlot {
export const enum Foo {
Bar = 1,
Moo = 2,
}
}
export default uPlot test.ts: import uPlot from './uPlot';
console.log(uPlot.Foo.Bar); test.js: "use strict";
exports.__esModule = true;
console.log(1 /* Bar */); |
this doesnt seem like a difficult thing to support, and is fairly straightforward without tricky corner cases. i think if you open an esbuild issue, evan would add it. |
well, we have a lot of code like this in Grafana currently: which would need to be reworked. we did have some internal discussion during the namespace removal and the general thought was that enforcing the uPlot prefix to every type was maybe not too necessary since more often than not the types are unique and you can always alias via i'm not 100% convinced that having to import uPlot twice and using i feel the whole thing is rather subjective and dependent on the coding style. i guess there is a compelling argument that React uses a namespace for all its types. cc @zefirka thoughts? one thing is for sure: this won't happen in a 1.6.x release. |
I don't know why that import statement in your screenshot doesn't work when using a namespace, since in react you can do: import React from 'react'
type T = React.ReactNode or import React, { ReactNode } from 'react'
type T = ReactNode |
I don't have a strong opinion due to this topic is mostly about code style. Currently we're using import uPlot, {Scale as uScale, Options as uOptions} from 'uplot'; So I prefer to keep it this way. But If this will work I don't see why not to allow to use both styles. |
yeah, ideally we can get it working both ways. |
I took a look at how the react declarations are defined and I got this working: uPlot.d.ts: declare class uPlot {
}
export = uPlot;
declare namespace uPlot {
interface Series {
k: boolean
}
}
export as namespace uPlot; test.ts: import uPlot, { Series } from './uPlot'
const s1: Series = { k: true }
const s2: uPlot.Series = { k: true }
const p = new uPlot() |
Grafana built without errors, so that's looking better :) but it looks like this method screws up module augmentation? it complains about "Import declaration conflicts with local declaration of uPlot". so rather than extending it, it masks it. import uPlot, { Series } from './uPlot'
declare namespace uPlot {
interface Series {
k: boolean
}
}
const s1: Series = { k: true };
const s2: uPlot.Series = { k: true };
const p = new uPlot(); |
If it screws module augmentation, I would rather prefer module augmentation not namespaces. Because namespaces are just about how it looks, but module augmentation allows you to extend types through whole module which, I guess, really useful feature when you're about to implement wrappers and plugins for uPlot. |
ok, i tried this again and it does all work properly if you use import uPlot, { Series, Options } from 'uplot';
declare module 'uplot' {
interface Series {
foo?: boolean
}
}
const s1: Series = { foo: true, stroke: "red" };
const s2: uPlot.Series = { foo: true, stroke: "red" };
let opts: Options = {
width: 300,
height: 300,
series: [
{},
s1,
s2,
]
};
new uPlot(opts, [[0, 1], [0, 1]], document.body); |
Hey @leeoniya 👋 Since this commit from v1.4.0, all the types/interfaces related to uPlot are no longer in a namespace:
Before
After
or
or
With a namespace that is named the same as the uPlot class like it was before, we can use the TypeScript and JavaScript values at the same time.
The text was updated successfully, but these errors were encountered: