Hur man får lodash.tonumber att fungera med import() och CommonJS enhetstest i Typescript?


Min tsconfig.json är:

{
    "compilerOptions": {
        "target": "es5",
        "module": "esnext",
        "moduleResolution": "node",
        "allowSyntheticDefaultImports": true
    }
}

Och eftersom lodash.tonumber inte har några typer, så deklarerade jag det så här:

// lib.d.ts
declare module "lodash.tonumber" {
    function toNumber(value: any): number;
    export = toNumber;
}

Sedan importerar jag biblioteket så här:

// index.ts
/// <reference path="./lib.d.ts" />
import toNumber from "lodash.tonumber";
export { toNumber }

Det fungerar perfekt med import() som förväntat.

När jag vill lägga till en enhetstest för index.ts, eftersom det körs på nodejs, så bör jag kompilera det med tsconfig.json som:

{
    "compilerOptions": {
        "target": "esnext",
        "module": "commonjs",
        "allowSyntheticDefaultImports": true
    }
}

Efter att jag kört testet visas felet: lodash_tonumber_1.default is not a function, den genererade js-filen är:

// index.js
/// <reference path="./lib.d.ts" />
var lodash_tonumber_1 = require("lodash.tonumber");
exports.toNumber = lodash_tonumber_1.default;

Dokumentet sa att lodash.tonumber bör användas så här:

const toNumber = require("lodash.tonumber");
console.log(toNumber("123"));

Så den genererade js-filen är fel, min tsconfig.json kan vara fel någonstans, så vad är fel?

Jag försökte ändra koden till:

// index.ts
/// <reference path="./lib.d.ts" />
import toNumber = require("lodash.tonumber");
export { toNumber }

För enhetstestet (modul=commonjs) genererade det korrekt var toNumber=require("lodash.tonumber");, och så fungerar det;

Men för min vanliga module=esnext-uppbyggnad gick det sönder, eftersom det inte genererade import toNumber from "lodash.tonumber";, körtidsfelet är ReferenceError: toNumber is not defined,

Jag kollar också lodash.toNumber js-koden:

function toNumber(value) {
  if (typeof value == 'number') {
    return value;
  }
  ...
}

module.exports = toNumber;

Så mina typer bör vara korrekta.

Vad kan jag göra härnäst?

Svar #1

// lib.d.ts
declare module "lodash.tonumber" {
    function toNumber(value: any): number;
    export = toNumber;
    namespace toNumber { }
}

Att deklarera ett namnrymd med samma namn fungerar.