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.