我读过TypeScript module resolution的工作原理。
我有以下存储库:ts-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-di';
找不到模块' ts-di'的声明文件。 ' /path/to/node_modules/ts-di/dist/index.js'隐含地有一个“任何”的类型。
然而,如果我导入如下,那么一切正常:
import {Injector} from '/path/to/node_modules/ts-di/dist/index.js';
我做错了什么?
答案 0 :(得分:164)
以下是另外两个解决方案
当模块不属于你时 - 尝试从@types
安装类型:
npm install -D @types/module-name
如果上述安装错误 - 请尝试将import
语句更改为require
:
// import * as yourModuleName from 'module-name';
const yourModuleName = require('module-name');
答案 1 :(得分:94)
如果您要导入的第三方模块'foo'
没有提供任何类型,可以在库本身或@types/foo
包中生成(从.d.ts
生成{3}}存储库),然后您可以通过在具有// foo.d.ts
declare module 'foo';
扩展名的文件中声明模块来消除此错误:
foo
然后,当您导入any
时,只需键入// foo.d.ts
declare module 'foo' {
export function getRandomNumber(): number
}
即可。
或者,如果您想要自己打字,也可以这样做:
import { getRandomNumber } from 'foo';
const x = getRandomNumber(); // x is inferred as number
然后这将正确编译:
any
您不必为模块提供完整的打字,足以满足您实际使用的位数(并且需要适当的打字),所以如果它非常容易您使用的是相当少量的API。
另一方面,如果您不关心外部库的类型,并希望所有没有打字的库都导入.d.ts
,您可以将其添加到{{1}的文件中}} extension:
declare module '*';
这样做的好处(也就是缺点)是你可以导入任何东西,TS会编译。
答案 2 :(得分:67)
当你想要两天并且发现这样的感觉时:只需从.js
中的"main": "dist/index.js"
移除package.json
,一切正常!
"main": "dist/index",
UPD :如果您有自己的npm套餐,这个答案是相对的,如果没有 - 请参阅my answer below。
如果上述答案未解决导入您的模块,请尝试在typings
中添加package.json
:
"main": "dist/index",
"typings": "dist/index",
当然,这里是文件夹dist
- 它存储模块的文件。
答案 3 :(得分:28)
对于其他人,请尝试将.js文件重命名为.ts
编辑:
您还可以将"allowJs": true
添加到tsconfig文件中。
答案 4 :(得分:21)
TypeScript基本上是在实现规则,并在代码中添加类型,以使代码更加清晰和准确,原因是Javascript缺乏约束。 TypeScript要求您描述数据,以便编译器可以检查您的代码并查找错误。如果您使用的是不匹配的类型,超出范围或尝试返回其他类型,则编译器会通知您。
因此,当您使用带有TypeScript的外部库和模块时,它们需要包含描述该代码中的类型的文件。这些文件称为扩展名为d.ts
的类型声明文件。 npm模块的大多数声明类型已经编写好了,您可以使用npm install @types/module_name
将它们包括在内(其中module_name是要包含其类型的模块的名称)。
但是,有些模块没有类型定义,为了使错误消失并使用import * as module_name from 'module-name'
导入模块,请在项目的根目录中创建一个文件夹typings
,在其中创建一个带有您的模块名称的新文件夹,并在该文件夹中创建一个module_name.d.ts
文件并写入declare module 'module_name'
。之后,只需转到您的tsconfig.json
文件,然后在"typeRoots": [ "../../typings", "../../node_modules/@types"]
中添加compilerOptions
(具有正确的文件夹相对路径),以使TypeScript知道可以在哪里找到库的类型定义。和模块,并向文件添加新属性"exclude": ["../../node_modules", "../../typings"]
。
这是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规则。
答案 5 :(得分:6)
如果您需要快速修复,只需在导入之前添加以下内容即可:
// @ts-ignore
答案 6 :(得分:4)
不幸的是,包编写者是否为声明文件而烦恼。我倾向于做的是index.d.ts
这样的文件,其中将包含各种程序包中所有缺少的声明文件:
Index.ts:
declare module 'v-tooltip';
declare module 'parse5';
declare module 'emoji-mart-vue-fast';
答案 7 :(得分:3)
使用带有以打字稿编写的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-module
不存在,因此我在导入my-module.d.ts
的文件旁边添加了一个my-module
文件,并显示了建议的行。然后我得到了错误:
Namespace '"my-module"' has no exported member 'Client'.
如果我在js应用程序中使用客户端,则该客户端实际上已导出并且可以正常工作。另外,上一条消息还告诉我编译器正在寻找正确的文件(/node_modules/my-module/lib/index.js
my-module/package.json
元素中定义了"main"
)。
我通过告诉编译器我不在乎隐式any
来解决了这个问题,也就是说,我将false
文件的以下行设置为tsconfig.json
:
"noImplicitAny": false,
答案 8 :(得分:3)
这种方式对我有用:
1.在声明文件中添加自己的声明,例如index.d.ts(可能在项目根目录下)django-subdomains
2.将您的index.d.js添加到tsconfig.json
declare module Injector;
答案 9 :(得分:3)
我在这里尝试了所有方法,但是对我来说,这是一个完全不同的问题:
我必须从*.d.ts
中删除所有导入语句:
import { SomeModuleType } from '3rd-party-module';
删除错误后消失了...
说明:
当我们在*.d.ts
文件中声明一个模块时,Typescript编译器会自动将其拾取为 ambient 模块(不需要显式导入的模块)。一旦指定了import ... from ...
,该文件即成为普通(ES6)模块,因此将不会自动被拾取。因此,如果您仍然希望其表现为 ambient 模块,请使用其他导入样式,如下所示:
type MyType: import('3rd-party-module').SomeModuleType;
答案 10 :(得分:2)
这就是我让它工作的方式。
就我而言,我使用了一个没有定义类型的库:react-mobile-datepicker
一个。在 /src
中创建一个文件夹。就我而言,我使用了以下路径:/src/typings/
.
B.创建一个 .d.ts
文件。对于我的示例:/src/typings/react-mobile-datepicker.d.ts
c.我使用以下代码扩展其属性并使其类型安全:
declare module 'react-mobile-datepicker' {
class DatePicker extends React.Component<DatePickerProps, any> {}
interface DatePickerProps {
isPopup?: boolean;
theme?: string;
dateConfig?: DatePickerConfig;
}
export interface DatePickerConfig {
prop1: number;
pro2: string;
}
export default DatePicker;
}
d。像通常在使用 3rd 方库的地方一样导入您的类型。
import DatePicker, { DatePickerConfig, DatePickerConfigDate } from 'react-mobile-datepicker';
e.更改 tsconfig.json
并添加这段代码:
{
"compilerOptions": {
//...other properties
"typeRoots": [
"src/typings",
"node_modules/@types"
]
}}
链接到我用作来源的文章:
https://templecoding.com/blog/2016/03/31/creating-typescript-typings-for-existing-react-components
https://www.credera.com/insights/typescript-adding-custom-type-definitions-for-existing-libraries
答案 11 :(得分:2)
简单地解决您的问题是:
// 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
答案 12 :(得分:2)
您要做的是编辑您的TypeScript Config文件(tsconfig.json)并添加一个新的键值对,如下所示:
pip3.8
例如: “ noImplicitAny”:否, “ allowJs”:是的, “ skipLibCheck”:是的, “ esModuleInterop”:是的, 继续。...
答案 13 :(得分:1)
如果您在 Webstorm 中看到此错误,并且您刚刚安装了该软件包,则您可能需要重新启动打字稿服务,然后它才会被接收。 >
Restart Typescript Service
答案 14 :(得分:1)
如果导入不适合您
import * as html2pdf from 'html2pdf.js';
注释代码,将下面的脚本文件保留在官方文档中给出的 index.html 中。
<script src="https://rawgit.com/eKoopmans/html2pdf/master/dist/html2pdf.bundle.min.js"></script>
并在您使用的组件中声明 html2pdf 变量。
declare var html2pdf: any;
就是这样。我被这个问题困了两天,终于解决了。
答案 15 :(得分:1)
如果您已经安装了模块但仍然出现错误,一个简短而甜蜜的解决方案是通过在该行上方添加以下行来忽略错误消息
// @ts-ignore: Unreachable code error
答案 16 :(得分:0)
检查"tsconfig.json"
文件中的编译选项"include"
和"exclude"
。如果它不存在,只需通过通知您的 root 目录来添加它们。
// tsconfig.json
{
"compilerOptions": {
...
"include": [
"src",
],
"exclude": [
"node_modules",
]
}
我只是通过从"*.spec.ts"
中删除扩展语句"exclude"
来解决了这个愚蠢的问题,因为当在这些文件中包含"import"
时,总会出现问题。
答案 17 :(得分:0)
我正在从react-native-button导入Button,并且出现此错误,如图所示:
我把戏。我进入了node_modules / react-native-button /文件夹,并复制Button.js文件的内容。创建一个名为Button.d.ts的新文件,然后将内容粘贴到其中。保存它,错误消失了!不知道原因,但是现在它已经消失了!
答案 18 :(得分:0)
npm install --save typescript @types/node @types/react @types/react-dom @types/jest
yarn add typescript @types/node @types/react @types/react-dom @types/jest
答案 19 :(得分:0)
解决方案:您所要做的就是编辑您的 TypeScript 配置文件 tsconfig.json
并添加一个新的键值对为
"compilerOptions": {
"noImplicitAny": false
}
答案 20 :(得分:0)
即使在已经安装了模块和类型并多次重新加载我的IDE的情况下,我也感到困惑了一段时间。
在我看来,解决此问题的方法是终止终端进程,删除node_modules
,清除节点程序包管理器缓存并重新进行install
,然后重新加载编辑器。
答案 21 :(得分:-1)
Could not find a declaration file for module 'busboy'. 'f:/firebase-cloud-
functions/functions/node_modules/busboy/lib/main.js' implicitly has an ‘any’
type.
Try `npm install @types/busboy` if it exists or add a new declaration (.d.ts)
the file containing `declare module 'busboy';`
对于我来说,该问题已解决:,您要做的就是编辑TypeScript配置文件(tsconfig.json
)并添加新的键值对,如下所示:
"noImplicitAny": false
答案 22 :(得分:-5)
需要模块帮助,而不是导入...
const React = require('react');
答案 23 :(得分:-8)
只需使用以下代码即可将其导入:
var _ = require('your_module_name');