我分发了一个Node.js模块,其类型附加为d.ts
文件。该模块没有公开默认的导出,但是由于某种原因,Typescript允许从该模块执行默认的导入,并且该默认的导入错误地公开了所有命名的导出,这允许错误地使用该模块并导致运行时崩溃。
module.js
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
exports.foo = function foo () {
console.log("foo")
}
module.d.ts
export declare function foo ()
tsconfig.json
{
"compilerOptions": {
"target": "esnext",
"moduleResolution": "node",
"experimentalDecorators": true,
"allowJs": true,
"esModuleInterop": true,
"noEmit": true
}
}
import { foo } from "./module"
foo()
按预期工作,打印“ foo”。
import module from "./module"
module.bar()
按预期方式工作,无法编译:
/Users/semenov/xxx/node_modules/ts-node/src/index.ts:261
return new TSError(diagnosticText, diagnosticCodes)
^
TSError: ⨯ Unable to compile TypeScript:
test.ts(3,8): error TS2339: Property 'bar' does not exist on type 'typeof import("/Users/semenov/xxx/module")'.
import module from "./module"
module.foo()
没有像我期望的那样给出Typescript编译错误。相反,它在运行时崩溃:
/Users/semenov/xxx/test.ts:3
module.foo()
^
TypeError: Cannot read property 'foo' of undefined
at Object.<anonymous> (/Users/semenov/xxx/test.ts:3:8)
at Module._compile (internal/modules/cjs/loader.js:701:30)
at Module.m._compile (/Users/semenov/xxx/node_modules/ts-node/src/index.ts:439:23)
at Module._extensions..js (internal/modules/cjs/loader.js:712:10)
at Object.require.extensions.(anonymous function) [as .ts] (/Users/semenov/xxx/node_modules/ts-node/src/index.ts:442:12)
at Module.load (internal/modules/cjs/loader.js:600:32)
at tryModuleLoad (internal/modules/cjs/loader.js:539:12)
at Function.Module._load (internal/modules/cjs/loader.js:531:3)
at Function.Module.runMain (internal/modules/cjs/loader.js:754:12)
at Object.<anonymous> (/Users/semenov/xxx/node_modules/ts-node/src/bin.ts:157:12)
如何在d.ts
文件中指定模块不提供默认导出(并为测试用例3给出编译错误)?还是将默认导出类型设置为never
,void
或类似的名称,以便至少不允许使用module.foo
?
我知道我可以在项目中禁用esModuleInterop
,但是它将停止导入大多数其他cjs程序包,包括那些没有类型的程序(例如,import path from "path"
将不会编译)。