我阅读了TypeScript模块解析的工作原理。

我有以下存储库:@tsstack/di。编译后,目录结构如下:

├── dist
│   ├── annotations.d.ts
│   ├── annotations.js
│   ├── index.d.ts
│   ├── index.js
│   ├── injector.d.ts
│   ├── injector.js
│   ├── profiler.d.ts
│   ├── profiler.js
│   ├── providers.d.ts
│   ├── providers.js
│   ├── util.d.ts
│   └── util.js
├── LICENSE
├── package.json
├── README.md
├── src
│   ├── annotations.ts
│   ├── index.ts
│   ├── injector.ts
│   ├── profiler.ts
│   ├── providers.ts
│   └── util.ts
└── tsconfig.json

在package.json中,我写了“main”:“dist/index.js”。

在Node.js中,一切正常,但TypeScript:

import {Injector} from '@ts-stack/di';

找不到模块“@ts stack/di”的声明文件/path/to/node_modules/@tsstack/di/dist/index.js”隐式具有“any”类型。

然而,如果我按如下方式导入,那么一切都正常:

import {Injector} from '/path/to/node_modules/@ts-stack/di/dist/index.js';

我做错了什么?


当前回答

我在使用节点模块和用typescript编写的react应用程序时遇到了同样的问题。使用npm i-save my module成功安装了模块。它是用javascript编写的,并导出一个Client类。

具有:

import * as MyModule from 'my-module';
let client: MyModule.Client = new MyModule.Client();

编译失败,错误为:

Could not find a declaration file for module 'my-module'. 
'[...]/node_modules/my-module/lib/index.js' implicitly has an 'any' type.
  Try `npm install @types/my-module` if it exists or add a new declaration (.d.ts) file containing `declare module 'my-module';`

@types/my模块不存在,所以我在导入我的模块的文件旁边添加了一个my-module.d.ts文件,并添加了建议的行。然后我得到了错误:

Namespace '"my-module"' has no exported member 'Client'.

如果我在js应用程序中使用它,客户端实际上是导出的,并且正常工作。此外,前面的消息告诉我编译器正在查找正确的文件(/node_modules/my-module/lib/index.js是在my-modle/package.json“main”元素中定义的)。

我通过告诉编译器我不关心隐式的任何问题来解决这个问题,也就是说,我将tsconfig.json文件的以下行设置为false:

    "noImplicitAny": false,

其他回答

在大多数情况下,您可能会为依赖项安装一个类型包,无论是哪种方式,都可以在tsconfig.json文件中添加allowJs->true

import { io, Socket,SocketIOClient } from 'socket.io-client';

在component.ts之上添加这个在我的案例中是有效的。

在我看来,解决这个问题的三种不同方法都不起作用。一旦在package.json中将“type”设置为“module”,那么它将符合ES module而不是CommonJS语法。我能够根据package.json设置使用ES模块语法来解决这个问题。

import ws from 'ws'

export const create = (/** @type {string} */ accessToken) => {
    const WebSocket = ws;
    return new WebSocket(endpoint, accessToken, sslOptions);
}

这样,您就可以在“ws”模块中使用WebSocket类。这是一个节点模块的示例,但基本上可以将任何类型的节点模块和函数放在其中。

下面这些对我不起作用:

npm安装-D@types/module名称const foo=require('模块名称');

// index.d.ts
declare module 'foo';

tsconfig.json中的配置

"noImplicitAny": true,
"allowJs": true

如果需要快速修复,只需将其添加到导入行之前:

// @ts-ignore

在许多项目中,我面临着许多包的相同问题。所以我创建了Declarator,一个自动生成类型声明的npm包。

它基本上通过在后台运行tsc-emitDeclarationOnly来工作。

您可以从npm安装它:

npm install --save-dev declarator
yarn add -D declarator

然后创建一个简单的声明器.json文件:

{
  "$schema": "https://raw.githubusercontent.com/ArthurFiorette/declarator/master/schema.json",
  "packages": ["package1","package2"]
}

并创建一个脚本来运行它:

使用postinstall脚本将在每次安装包时运行它,这可能很有用

{
  "scripts": {
    "postinstall": "declarator"
  }
}

它不会生成强大的类型,在这一过程中您可能会遇到许多类型,但使用它比不使用它要好得多

阅读更多信息:https://github.com/ArthurFiorette/declarator#readme