我阅读了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';
我做错了什么?
在许多项目中,我面临着许多包的相同问题。所以我创建了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
由于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规则。
@ktretyak和@Retsam的答案是正确的,但我想添加一个完整的实时示例以及我必须做的事情:
错误:
错误TS7016(TS)找不到模块的声明文件'反应区域选择'。'C:/Repo/node_modules/react region select/lib/RegionSelect.js'隐式具有“any”类型。尝试npm i--save dev@types/react region select(如果存在)或添加新声明包含“声明模块”的(.d.ts)文件
运行npm i--save dev@types/react region select时出现错误:
npm错误!代码E404npm错误!404未找到-GEThttps://registry.npmjs.org/@类型%2反应区域选择-未找到npm错误!404'@类型/react-region-select@latest'不是在npm注册表中。npm错误!404你应该让作者发布它(或者自己使用这个名字!)npm错误!404注意您也可以从npm tarball、文件夹、httpurl或giturl安装。
考虑到create-react-app创建了一个名为react-app-env.d.ts的文件,我尝试将声明模块放入“react region select”;但我还是收到了错误。
然后,我在src中创建了一个名为typings的新文件夹,以及名为react-region-select.dts的文件
declare module 'react-region-select';
这样做之后,错误消失了,我可以像文档所述那样导入它:
import RegionSelect from "react-region-select";
https://github.com/casavi/react-region-select