I have an old JavaScript library that I wrote to work with AMD and CommonJS. I forgot the original source which influenced me to write the library in this way, but my JavaScript library is written in the following pattern.
(function(window) { 'use strict'; function getLib() { var mylib = {}; mylib.getSomething = function() { return 'x'; } mylib.getCar = function(make, model, year) { return { make: make, model: model, year: year }; } return mylib; } if(typeof module === 'object' && module && typeof module.exports === 'object') { module.exports = getLib(); } else { if(typeof(mylib) === 'undefined') { window.mylib = getLib(); } if(typeof define === 'function' && define.amd) { define('mylib', [], getLib()); } } })(this); How do I write a type definition d.ts file for this JavaScript library?
I attempted to write a d.ts as follows, but it does not work. In my Angular app, I put the following file node_modules/@types/mylib/index.d.ts.
interface Car { make: string; model: string; year: number; } interface MyLib { getSomething(): string; getCar(make: string, model: string, year: number): Car; } declare module "mylib" { export let mylib: MyLib } In my controller, I simply try to import the library and debug it to the console, but get undefined.
import {mylib} from 'mylib'; //IDE doesn't complain, seems to find the type def export class MyPage { constructor() { console.log(mylib); //undefined console.log(mylib.getCar('ford', 'f150', 2018)); //code won't reach here } } Note that the JavaScript package mylib is not on NPM but a private repository and I have already installed it (e.g. npm install mylib --save) to node_modules/mylib. I mention this because I am not sure where the type def file should go.
Any help is appreciated.
UPDATE:
Per the advice below, I've modified my d.ts file to look like the following and placed it in mylib/index.d.ts.
declare module "mylib" { let mylib: MyLib; export = mylib; } Now, I can import the library in two ways. First way.
import mylib from 'mylib'; Second way.
import * as mylib from 'mylib'; In VS Code, the IDE, there are no complaints (no red lines hinting at problems). Furthermore, I've modified tsconfig.json to look like the following.
{ "compileOnSave": false, "compilerOptions": { "baseUrl": "./", "outDir": "./dist/out-tsc", "sourceMap": true, "declaration": false, "module": "commonjs", "esModuleInterop": true, "moduleResolution": "node", "emitDecoratorMetadata": true, "experimentalDecorators": true, "target": "es5", "typeRoots": [ "node_modules/@types" ], "lib": [ "es2015.promise", "es2017", "dom" ] } } When I run ng build, I see the message below.
ERROR in node_modules/typescript/lib/lib.dom.d.ts(3268,88): error TS2344: Type 'SVGElementTagNameMap[K]' does not satisfy the constraint 'Node'. Type 'SVGSVGElement | SVGCircleElement | SVGClipPathElement | SVGDefsElement | SVGDescElement | SVGElli...' is not assignable to type 'Node'. Type 'SVGFEColorMatrixElement' is not assignable to type 'Node'. Types of property 'values' are incompatible. Type 'SVGAnimatedNumberList' is not assignable to type 'string[]'. Property 'includes' is missing in type 'SVGAnimatedNumberList'. node_modules/typescript/lib/lib.dom.d.ts(3626,85): error TS2344: Type 'SVGElementTagNameMap[K]' does not satisfy the constraint 'Node'. Type 'SVGSVGElement | SVGCircleElement | SVGClipPathElement | SVGDefsElement | SVGDescElement | SVGElli...' is not assignable to type 'Node'. Type 'SVGFEColorMatrixElement' is not assignable to type 'Node'. node_modules/typescript/lib/lib.dom.d.ts(10405,11): error TS2430: Interface 'SVGFEColorMatrixElement' incorrectly extends interface 'SVGElement'. Types of property 'values' are incompatible. Type 'SVGAnimatedNumberList' is not assignable to type 'string[]'. node_modules/typescript/lib/lib.dom.d.ts(14172,86): error TS2344: Type 'SVGElementTagNameMap[K]' does not satisfy the constraint 'Node'. Type 'SVGSVGElement | SVGCircleElement | SVGClipPathElement | SVGDefsElement | SVGDescElement | SVGElli...' is not assignable to type 'Node'. Type 'SVGFEColorMatrixElement' is not assignable to type 'Node'.
The "interesting" thing is that if I comment out the import then run ng build or ng serve, the compile error goes away. While the app is in live reload mode, I can simply uncomment the import, and though the compile error shows up, I can still use all the features of the library in the application.