Reputation: 4914
I started using Typescript recently and I came across the need to require an npm module inside my application. Since said npm module has no type definitions of it's own, I also decided to fork it and add my own. How hard can it be?
Here is the npm module I installed on my project:
/**
* Given a number, return a zero-filled string.
* From http://stackoverflow.com/questions/1267283/
* @param {number} width
* @param {number} number
* @return {string}
*/
module.exports = function zeroFill (width, number, pad) {
if (number === undefined) {
return function (number, pad) {
return zeroFill(width, number, pad)
}
}
if (pad === undefined) pad = '0'
width -= number.toString().length
if (width > 0) return new Array(width + (/\./.test(number) ? 2 : 1)).join(pad) + number
return number + ''
}
Simple enough, it just exports a single function. Now let's see how to get typescript work with it...
Definition
declare module "zero-fill"{
export function zeroFill(width:number, num:number, pad?:string|number):string
export function zeroFill(width:number):{(num:number, pad?:string|number):string}
}
Source code
import * as zeroFill from "zero-fill";
console.log(zeroFill(10, 10));
Generated code
"use strict";
exports.__esModule = true;
var zeroFill = require("zero-fill");
console.log(zeroFill(10, 10));
This one generates code that works, but at the same time gives an error. Also no autocomplete from my IDE.
Cannot invoke an expression whose type lacks a call signature. Type 'typeof "zero-fill"' has no compatible call signatures.
Definition
declare module "zero-fill"{
// Notice the default keywords
export default function zeroFill(width:number, num:number, pad?:string|number):string
export default function zeroFill(width:number):{(num:number, pad?:string|number):string}
}
Source
import zeroFill from "zero-fill";
console.log(zeroFill(10, 10));
Generated
"use strict";
exports.__esModule = true;
var zero_fill_1 = require("zero-fill");
console.log(zero_fill_1["default"](10, 10));
Here I prefer the syntax I use inside my typescript and the compiler seems to like it as well. Zero compiler errors and also type hinting works on IDEA. Too bad the generated code gives me an TypeError: zero_fill_1.default is not a function
error when run...
Definition
declare module "zero-fill"{
function zeroFill(width:number, num:number, pad?:string|number):string
function zeroFill(width:number):{(num:number, pad?:string|number):string}
export {zeroFill};
}
Source
import {zeroFill} from "zero-fill";
console.log(zeroFill(10, 10));
Generated
"use strict";
exports.__esModule = true;
var zero_fill_1 = require("zero-fill");
console.log(zero_fill_1.zeroFill(10, 10));
Exactly the same as before... The compiler and IDE like this but the runtime doesn't
I could go on but I believe you get the idea. Is it possible to make this npm module usable inside typescript without making changes to it's actual code? What am I doing wrong and how can I import this function properly?
Upvotes: 1
Views: 67
Reputation: 4198
I believe you're looking for this documentation
declare module 'zero-fill' {
function zeroFill() /* etc. */
export = zeroFill;
/* for any additional types */
namespace zeroFill {
interface FooBar { /* ... */ }
}
}
then import it as:
import zeroFill = require('zero-fill');
Upvotes: 2