0

I am trying to define types for a module I installed via npm.

This is the exported module. I'd rather not make changes to this file since I'd like to merge back to the original repo without introducing BCs

/**
 * 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 + ''
}

This is the definition I wrote for this file

declare module "zero-fill"{
    export default function zeroFill(width:number, num:number, pad?:string|number):string;
    export default function zeroFill(width:number):{(num:number, pad?:string|number):string};
}

And here is an example usage:

import * as zeroFill from "zero-fill";
zeroFill(2,0);

What confuses me is that the compiler both gives me this error:

Cannot invoke an expression whose type lacks a call signature. Type 'typeof "zero-fill"' has no compatible call signatures.

while at the same time it compiles the typescript and I see it running in the browser. What seems to be the problem?

Loupax
  • 4,728
  • 6
  • 41
  • 68

2 Answers2

2

Here is what I ended up doing

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
}

Usage:

import zeroFill = require("zero-fill")
zeroFill(4, 1) // '0001'
zeroFill(10, 55) // '0000000055'
zeroFill(1, 1) // '1'
Loupax
  • 4,728
  • 6
  • 41
  • 68
0

When you import * as zeroFill you're actually naming the module itself zeroFill. To call the function, you'd have to go zeroFill.zeroFill(2, 0), where the first zeroFill is the import alias and the second zeroFill is the function.

y2bd
  • 5,783
  • 1
  • 22
  • 25
  • There must be something really wrong with my compilation process... Doing `console.log(zeroFill)` shows me that it contains the function itself, not a container object. So if I replace `zeroFill()` with `zeroFill.zeroFill()` the compiler stops complaining but my application crashes... Will check again after I wake up... – Loupax May 01 '17 at 23:14
  • Is the definition file something you wrote yourself? It doesn't appear to directly correspond with the implementation. I think you should set the exports to default exports (`export default function zeroFill`) and then import the default export (`import zeroFill from 'zero-fill'`) because the module.exports in the implementation is a function itself, rather than a container object (as you've discovered). – y2bd May 01 '17 at 23:22
  • Yes and the exact same error occurs when I export the function as default. I updated the question accordingly – Loupax May 02 '17 at 05:29
  • Found [this](https://github.com/Microsoft/TypeScript/issues/7554) issue on the TS issue tracker. Will give it a go when possible – Loupax May 02 '17 at 06:38