不幸的是,这些事情目前没有很好的记录,但即使您能够让它工作,让我们检查一下您的配置,以便您了解每个部分正在做什么以及它与打字稿如何处理和加载打字的关系。
首先让我们回顾一下您收到的错误:
error TS2688: Cannot find type definition file for 'lodash'.
这个错误实际上不是来自您的导入或引用,也不是您尝试在 ts 文件中的任何位置使用 lodash。相反,它来自于对如何使用的误解typeRoots
and types
属性,所以让我们更详细地了解这些属性。
事情是关于typeRoots:[]
and types:[]
属性是它们是NOT加载任意声明的通用方法(*.d.ts
) files.
这两个属性与新的 TS 2.0 功能直接相关,该功能允许从以下位置打包和加载类型声明:NPM 包.
理解这一点非常重要,这些仅适用于 NPM 格式的文件夹(即包含包.json or 索引.d.ts).
默认为typeRoots
is:
{
"typeRoots" : ["node_modules/@types"]
}
默认情况下,这意味着打字稿将进入node_modules/@types
文件夹并尝试加载它在其中找到的每个子文件夹作为npm 包.
重要的是要了解,如果文件夹没有类似 npm 包的结构,这将会失败。
这就是您的情况所发生的情况,也是您最初错误的根源。
您已将 typeRoot 更改为:
{
"typeRoots" : ["./typings"]
}
这意味着打字稿现在将扫描./typings
文件夹子文件夹并尝试将它找到的每个子文件夹作为 npm 模块加载。
所以让我们假设你刚刚typeRoots
设置为指向./typings
但还没有任何types:[]
属性设置。您可能会看到这些错误:
error TS2688: Cannot find type definition file for 'custom'.
error TS2688: Cannot find type definition file for 'global'.
这是因为tsc
正在扫描您的./typings
文件夹并查找子文件夹custom
and global
。然后它尝试将这些解释为 npm 包类型类型,但没有index.d.ts
or package.json
在这些文件夹中,所以你会得到错误。
现在我们来谈谈types: ['lodash']
您正在设置的属性。这是做什么的?默认情况下,打字稿将加载all它在您的文件夹中找到的子文件夹typeRoots
。如果您指定一个types:
属性它只会加载那些特定的子文件夹。
在你的情况下,你告诉它加载./typings/lodash
文件夹,但它不存在。这就是为什么你会得到:
error TS2688: Cannot find type definition file for 'lodash'
让我们总结一下我们所学到的知识。 Typescript 2.0 推出typeRoots
and types
用于加载打包的声明文件npm 包。如果您有自定义打字或单个松散d.ts
如果文件不包含在遵循 npm 包约定的文件夹中,那么这两个新属性不是您想要使用的。 Typescript 2.0 并没有真正改变它们的使用方式。您只需以多种标准方式之一将这些文件包含在您的编译上下文中:
直接将其包含在.ts
file:
///<reference path="../typings/custom/lodash.d.ts" />
包括./typings/custom/lodash.d.ts
在你的files: []
财产。
包括./typings/index.d.ts
在你的files: []
属性(然后递归地包含其他类型。
Adding ./typings/**
给你的includes:
希望根据这次讨论,您能够说出为什么您对自己的想法做出了改变tsconfig.json
让事情再次运转起来。
EDIT:
我忘记提及的一件事是typeRoots
and types
属性实际上只对自动的加载全局声明。
例如,如果您
npm install @types/jquery
并且您使用默认的 tsconfig,那么 jquery types 包将自动加载并且$
将在您的所有脚本中可用,而无需执行任何进一步操作///<reference/>
or import
The typeRoots:[]
属性旨在添加其他位置,其中类型packages将自动加载。
The types:[]
属性的主要用例是禁用自动加载行为(通过将其设置为空数组),然后仅列出您想要全局包含的特定类型。
从各种类型加载类型包的另一种方法typeRoots
就是使用新的///<reference types="jquery" />
指示。注意types
代替path
。同样,这仅对全局声明文件有用,通常是那些不这样做的文件import/export
.
现在,这是导致混淆的事情之一typeRoots
。记住,我说过typeRoots
是关于模块的全局包含。但@types/folder
还涉及标准模块分辨率(无论您的typeRoots
环境)。
具体来说,显式导入模块总是会绕过所有includes
, excludes
, files
, typeRoots
and types
选项。所以当你这样做时:
import {MyType} from 'my-module';
所有上述属性都被完全忽略。期间的相关属性模块分辨率 are baseUrl
, paths
, and moduleResolution
.
基本上,使用时node
模块解析,它将开始搜索文件名my-module.ts
, my-module.tsx
, my-module.d.ts
从您指向的文件夹开始baseUrl
配置。
如果找不到该文件,则会查找名为的文件夹my-module
然后搜索一个package.json
with a typings
财产,如果有package.json
or no typings
里面的属性告诉它要加载哪个文件,然后它将搜索index.ts/tsx/d.ts
在该文件夹中。
如果仍然不成功,它将在node_modules
文件夹从你的开始baseUrl/node_modules
.
另外,如果没有找到这些,它会搜索baseUrl/node_modules/@types
对于所有相同的事情。
如果仍然找不到任何内容,它将开始转到父目录并搜索node_modules
and node_modules/@types
那里。它将继续向上移动目录,直到到达文件系统的根目录(甚至在项目外部获取节点模块)。
我想强调的一件事是模块解析完全忽略任何typeRoots
你设置。所以如果你配置了typeRoots: ["./my-types"]
,在显式模块解析期间不会搜索它。它仅充当一个文件夹,您可以在其中放置要供整个应用程序使用的全局定义文件,而无需进一步导入或引用。
最后,您可以使用路径映射覆盖模块行为(即paths
财产)。例如,我提到任何定制typeRoots
尝试解析模块时不会咨询。但如果你愿意,你可以让这种行为发生,如下所示:
"paths" :{
"*": ["my-custom-types/*", "*"]
}
其作用是对于与左侧匹配的所有导入,在尝试包含它之前尝试像右侧那样修改导入(*
右侧代表您的初始导入字符串。例如,如果您导入:
import {MyType} from 'my-types';
它会首先尝试导入,就像您编写的一样:
import {MyType} from 'my-custom-types/my-types'
然后,如果没有找到,它将在没有前缀的情况下再次尝试(数组中的第二项只是*
这意味着初始导入。
因此,通过这种方式,您可以添加其他文件夹来搜索自定义声明文件甚至自定义.ts
您希望能够的模块import
.
您还可以为特定模块创建自定义映射:
"paths" :{
"*": ["my-types", "some/custom/folder/location/my-awesome-types-file"]
}
这会让你做
import {MyType} from 'my-types';
但随后读取这些类型some/custom/folder/location/my-awesome-types-file.d.ts