I'm writing a node js typescript library (for use in cli app context) which has a dependency on a js library jinxed, which has no typescript type declarations. I have been following information at Typescript declaration files
jinxed is a simple library that currently exports a single function via module.exports { ... }, it is not intended to be the sole export from the library, (since it will be expanded in the future). So the exported function is a member of the export object.
The problem is how do I consume this within a typescript library. After reading all the typescript declaration documentation, this is still not clear to me how to do this.
The first problem to solve is which declaration template to pick from Typescript declaration file templates.
I decided that the appropriate template to use to enable consuming jinxed from typescript is module.d.ts (I stand to be corrected though).
So my client typescript library (widget) looks like this:
widget/
lib/
externalTypes/
jinxed/
index.d.ts
index.ts
So the above shows me defining a type file for the external dependency jinxed according to the instructions in the template file; ie create a folder whose name matches the name of the external dependency and place an index.d.ts file inside it.
widget/lib/externalTypes/jinxed/index.d.ts:
export function functify(obj: any): string;
On the consuming side; ie inside my index.ts file (widget/lib/index.ts):
/// <reference types="./externalTypes/jinxed" />
import jinxed = require('jinxed');
const TestObject:any = {
name: 'dvorak',
occ: 'watchman'
};
jinxed.functify(TestObject);
[PS: I have also tried:
let jinxed = require('./externalTypes/jinxed'); ( ... but this just results in an error about using the require statment)
]
But when compiled results in the following error message:
ERROR in /Users/User/dev/github/js/widget/lib/index.ts ./lib/index.ts [tsl] ERROR in
/Users/User/dev/github/js/widget/lib/index.ts(4,25) TS7016: Could not find a declaration file for module 'jinxed'. '/Users/User/dev/github/js/widget/node_modules/jinxed/index.js' implicitly has an 'any' type.
(Apologies for the error message looking a bit ugly, formatting issues)
[
And for the sake of completeness, the content of jinxed is as follows:
'use strict';
function functify (obj) {
return JSON.stringify(obj, (key, val) => {
return (typeof val === 'function') ? '_function_' : val;
});
}
module.exports = {
functify: functify
}
]
The error message is indicating that it can't find the declaration file for jinxed, but I have used the
/// <reference...
to specify the type file to use, so I don't know what the problem is.
The dependencies in widget packaage.json is as follows:
"dependencies": {
"@types/ramda": "^0.26.19",
"jinxed": "0.0.1",
"ramda": "^0.26.1",
"xpath": "0.0.27" },
The tsconfig file is:
{
"compilerOptions": {
"allowJs": true,
"alwaysStrict": true,
"module": "commonjs",
"moduleResolution": "Node",
"noImplicitAny": true,
"sourceMap": true,
"strictNullChecks": true,
"target": "es5",
"types": [],
"lib": [
"es5",
"es2015",
"es6",
"dom"
]
},
"include": [
"lib/**/*"
],
"exclude": [
"node_modules",
"**/*.spec.ts"
]
}
The "main" entry in package.json is:
"main": "./lib/index.ts",
Also, I would like to know if the way I have structured external type dependencies seems reasonable. IE, let's say, I am trying to consume another external js library in a similar way to that illustrated above for jinxed; I would assume, that I would create another folder under externalTypes that matches the name of that dependency and populate it with its own index.d.ts. Is that correct or am I barking up the wrong tree?
EDIT: (I found the solution to this problem via this issue, but I don't really userstand this.
In the index.d.ts, I have updated it to be as follows:
declare module 'jinxed' {
export function functify(obj: any): string;
}
... and this does actually work.
However, I don't understand the declare module statement, in particular, why the names jinxed is inside quotes (remove the quotes and you get an error: TS7016: Could not find a declaration file for module 'jinxed'). So far I have not found the correct typescript template that this corresponds to, so I can't get a good explanation of why this works.