Chart.js
Chart.js copied to clipboard
using TypeScript type definitions in code without modules
Do the TS type definitions in Chart.js 3.0 support code written old-school web way, without modules, with the library included in HTML using <script>?
I have a file that uses Chart.js this way, written in TypeScript, and it worked fine with Chart.js 2.x, with the types from DefinitelyTyped. I'm trying to upgrade to 3.0 now, and the TypeScript compiler doesn't seem to recognize the name Chart. I can see it's going through the type files, but in the end it somehow doesn't make this declaration available to my script (error TS2304: Cannot find name 'Chart'.).
I suspect this may be because (as I understand?) the objects are now exported there using the CommonJS way, but I'm not actually importing any modules in my script, since it relies on the Chart object being imported into window earlier. But I have a pretty poor understanding of how JS modules work in general, so I'm not sure.
Based on some simple tests, I can see that a class declared like this (which is how type declarations for Chart.js 2.x looked like) works when used without an import:
declare class Chart {
id: string;
}
But a class declared like this (which is how type declarations for Chart.js 3.x look like) doesn't:
export declare class Chart {
id: string;
}
I've found some suggestions on the web that adding a wrapper script that imports the contents of the module and then re-exports everything using declare global could fix this, but I've tried a few different ways and nothing seems to give the results I want.
Given that Chart.js 2.x could be used this way, and Chart.js 3.x supports being used this way in plain JS (using the non-ESM variant of the build from a CDN), is this something you could possibly add? Or at least, can you provide tips on how to work around this on the user side, if that's actually possible?
Steps to Reproduce
- have a
.tsfile that references theChartclass from the global namespace without usingimport - add type declaration files from the
typesfolder into the project, or installchart.jstonode_modulesusingnpm - run the TypeScript compiler with
npx tscon that TypeScript file
Expected Behavior
The TypeScript compiler should load all type definitions for Chart.js. When parsing a TS file that uses Chart.js 2.x, it should only print errors for the parts of code that call APIs that have been removed in 3.x.
Current Behavior
The TypeScript compiler seems to load type definitions (npx tsc --traceResolution shows it's going through the files), but it still doesn't recognize any APIs from Chart.js:
error TS2304: Cannot find name 'Chart'.
error TS2503: Cannot find namespace 'Chart'.
Environment
- Chart.js version: 3.6.1
- TypeScript compiler version: 4.4.3
So lets see if I understand correctly:
- You have a .html (or equivalent) file referencing
chart.jswithscripttag. - You have a TS project that you compile and reference the result in another
scripttag - You expect
tscto know about globalChartwithout importing it?
More or less, yeah. This used to work with Chart.js 2.9.3 from which I'm upgrading, with type definitions from @types/chart.js (https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/chart.js), which were defined in a global context (declare class Chart). As I understand, in this setup the TypeScript compiler somehow automatically finds relevant type definitions without the need for any explicit imports.
With 3.x I tried adding an explicit TypeScript types import like this:
/// <reference types="chart.js" />
which makes the compiler step through all provided type files (as seen when run with --traceResolution), but in the end it still doesn't understand the name Chart.
Here's a sample project:
- https://github.com/mackuba/chartjs_sample - 2.x -
npx tscworks - https://github.com/mackuba/chartjs_sample/tree/chartjs_v3 - 3.x -
npx tscsaysCannot find name 'Chart'.
@mackuba if I remember correctly, the /// <reference is looking for types in the @types folder. So you need to write a simple script to copy the chartjs types.
I don't think it's an issue of it not finding the files, I think it's that the types are exported in the module way and the TS compiler doesn't understand "Chart" used in the global scope. If I understand this correcly.
This is the log from npx tsc --traceResolution when I add the <reference>, take a look: https://gist.github.com/mackuba/e98e6278a474a686c932b159ababfac6
Maybe you can use the import type {Chart} from 'chart.js' pattern to work around this? (I'm writing on mobile, so too hard to test)
@kurkle not without many more changes - if I add that, tsc starts complaining about the properties I add to Window, and global functions that are called from HTML, and so on… and then that import gets printed to the resulting JS, and the browser fails to load it at all. I would have to switch the whole JS to module style, but I don't want to do that, I want to keep using it in the classic non-module way like before in 2.x.
@mackuba You could augment the window interface (see link for reference)
Hi, we would love to have this feature too. The change is very simple, it's enough to add one line at the end of index.d.ts export as namespace chartjs; Link to typescript documentation : export as namespace chartjs;
Thanks
Here's a workaround that you can use until this is fixed:
Create your own .d.ts file, and add these lines:
import * as _chart from 'chart.js';
export = _chart.Chart;
export as namespace Chart;