我阅读了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';

我做错了什么?


当前回答

我已经尝试了这里的一切,但对我来说,这是一个完全不同的问题:我必须从*.d.ts中删除任何导入语句:

import { SomeModuleType } from '3rd-party-module';

删除错误后。。。

澄清:当我们在*.d.ts文件中声明一个模块时,Typescript编译器会自动将其作为环境模块(不需要显式导入的模块)。一旦我们指定了导入。。。从…起该文件现在成为一个正常(ES6)模块,因此不会自动拾取。因此,如果您仍然希望它作为环境模块,请使用不同的导入样式,如下所示:

type MyType: import('3rd-party-module').SomeModuleType;

其他回答

由于Javascript中缺少约束,TypeScript基本上是在实现规则并向代码中添加类型,以使代码更清晰、更准确。TypeScript要求您描述数据,以便编译器可以检查代码并查找错误。编译器将告诉您是否使用了不匹配的类型,是否超出了范围或试图返回不同的类型。因此,当您使用TypeScript的外部库和模块时,它们需要包含描述代码中类型的文件。这些文件被称为扩展名为d.ts的类型声明文件。npm模块的大多数声明类型都已编写,您可以使用npm install@types/module_name(其中module_name是要包含其类型的模块的名称)来包含它们。

但是,有些模块没有它们的类型定义,为了消除错误并使用import*作为“模块名”中的模块名导入模块,请在项目的根目录中创建一个文件夹类型,在其中创建一个带有模块名的新文件夹,并在该文件夹中创建模块名.d.ts文件并写入声明模块“模块名。”。之后,只需转到tsconfig.json文件,在compilerOptions中添加“typeRoots”:[“../../typings”,“../../node_modules/@types”](具有文件夹的正确相对路径),让TypeScript知道在哪里可以找到库和模块的类型定义,并在文件中添加一个新属性“exclude”:[。下面是一个tsconfig.json文件的示例:

{
    "compilerOptions": {
        "module": "commonjs",
        "noImplicitAny": true,
        "sourceMap": true,
        "outDir": "../dst/",
        "target": "ESNEXT",
        "typeRoots": [
            "../../typings",
            "../../node_modules/@types"
        ]
    },
    "lib": [
            "es2016"
    ],
    "exclude": [
        "../../node_modules",
        "../../typings"
    ]
}

通过这样做,错误将消失,您将能够遵守最新的ES6和TypeScript规则。

这种方式对我有效:

1.在声明文件(例如index.d.ts)中添加自己的声明(可能在项目根目录下)

declare module 'Injector';

2.将index.d.ts添加到tsconfig.json

  {
    "compilerOptions": {
        "strictNullChecks": true,
        "moduleResolution": "node",
        "jsx": "react",
        "noUnusedParameters": true,
        "noUnusedLocals": true,
        "allowSyntheticDefaultImports":true,
        "target": "es5",
        "module": "ES2015",
        "declaration": true,
        "outDir": "./lib",
        "noImplicitAny": true,
        "importHelpers": true
      },
      "include": [
        "src/**/*",
        "index.d.ts",   // declaration file path
      ],
      "compileOnSave": false
    }

一个简单的解决方案:

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

如果要声明对象的接口(推荐用于大型项目),可以使用:

// example.d.ts
declare module 'foo'{
    // example
    export function getName(): string
}

如何使用?易于理解的

const x = require('foo') // or import x from 'foo'
x.getName() // intellisense can read this

如果您已经安装了模块,但仍然收到错误,一个简短而简单的解决方案是通过在该行上方添加以下行来忽略错误消息

// @ts-ignore: Unreachable code error

不幸的是,包编写者是否对声明文件感到困扰,我们无法控制。我倾向于创建一个像index.d.ts这样的文件,其中包含各种包中所有缺失的声明文件:

索引.d.ts:

declare module 'v-tooltip';
declare module 'parse5';
declare module 'emoji-mart-vue-fast';

并在tsconfig.js中引用它:

"include": [
    "src/**/*.ts",
    "src/**/*.tsx",
    "src/**/*.vue",
    "tests/**/*.ts",
    "tests/**/*.tsx",
    "index.d.ts" // this
  ]