不幸的是,这些事情目前还没有得到很好的记录,但是即使您能够使其正常工作,我们也要仔细检查一下配置,以便您了解每个部分的工作以及它与打字稿处理和加载类型的关系。
首先让我们看一下您收到的错误:
error TS2688: Cannot find type definition file for 'lodash'.
实际上,此错误并非来自您的导入或引用,也不是您尝试在ts文件中的任何地方使用lodash的。而是由于对如何使用typeRoots
and types
属性有误解,因此让我们对其进行更多详细说明。
关于typeRoots:[]
和的事情types:[]
性能是它们不是通用的方式来加载任意声明(*.d.ts
)文件。
这两个属性与新的TS 2.0功能直接相关,该功能允许打包和加载NPM包中的键入声明。
了解这些非常重要,因为这些仅适用于NPM格式的文件夹(即,包含package.json或 index.d.ts)。
的默认typeRoots
值为:
{
"typeRoots" : ["node_modules/@types"]
}
默认情况下,这意味着打字稿将进入该node_modules/@types
文件夹,并尝试将在该文件夹中找到的每个子文件夹加载为一个 npm package。
重要的是要了解,如果文件夹没有类似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
和global
。然后,它试图将它们解释为npm包类型键入,但是这些文件夹中没有index.d.ts
或存在package.json
,因此您会收到错误消息。
现在让我们谈谈types: ['lodash']
您要设置的属性。这是做什么的?默认情况下,打字稿将加载在中找到的所有子文件夹typeRoots
。如果指定types:
属性,它将仅加载那些特定的子文件夹。
在您的情况下,您要告诉它加载./typings/lodash
文件夹,但该文件夹不存在。这就是为什么您得到:
error TS2688: Cannot find type definition file for 'lodash'
因此,让我们总结一下我们学到的知识。引入了Typescript 2.0 typeRoots
,types
用于加载打包在npm软件包中的声明文件。如果d.ts
遵循npm软件包约定,文件夹中不包含自定义类型或单个松散文件,则这两个新属性不是您要使用的属性。Typescript 2.0并没有真正改变它们的使用方式。您只需以多种标准方式之一将这些文件包括在编译上下文中:
直接将其包含在.ts
文件中:
///<reference path="../typings/custom/lodash.d.ts" />
包括./typings/custom/lodash.d.ts
在您的files: []
财产中。
包括./typings/index.d.ts
在您的files: []
媒体资源中(然后递归地包括其他类型。
添加./typings/**
到您的includes:
我们希望,在此基础上讨论,你就可以知道为什么你的变化,你疯了tsconfig.json
让事情再次合作。
编辑:
我忘记提到的一件事是,typeRoots
and types
属性实际上仅对自动加载全局声明有用。
例如,如果您
npm install @types/jquery
而且您使用的是默认的tsconfig,那么该jquery类型包将自动加载,并且$
在所有脚本中都可用,而无需进行任何进一步的操作///<reference/>
或import
该typeRoots:[]
属性旨在添加其他类型的软件包将从其自动加载的位置。
该types:[]
属性的主要用例是禁用自动加载行为(通过将其设置为空数组),然后仅列出要全局包含的特定类型。
从各种类型加载类型包的另一种方法typeRoots
是使用new ///<reference types="jquery" />
指令。请注意,types
而不是path
。同样,这仅对全局声明文件有用,通常不这样做import/export
。
现在,这是引起与混淆的原因之一typeRoots
。记住,我说的typeRoots
是关于模块的全球包含。但是,@types/folder
它也涉及标准模块分辨率(与您的typeRoots
设置无关)。
具体来说,明确导入模块总是绕过所有 includes
,excludes
,files
,typeRoots
和types
选项。因此,当您这样做时:
import {MyType} from 'my-module';
上面提到的所有属性都被完全忽略。在相关性模块的分辨率是baseUrl
,paths
和moduleResolution
。
基本上,当使用node
模块的分辨率,它会开始寻找一个文件名my-module.ts
,my-module.tsx
,my-module.d.ts
开始在文件夹中的指向baseUrl
配置。
如果找不到文件,则它将查找名为的文件夹my-module
,然后搜索package.json
带有typings
属性的文件夹,如果内部有package.json
或没有typings
属性告诉它要加载哪个文件,则将index.ts/tsx/d.ts
在该文件夹中搜索。
如果仍然无法成功,它将在node_modules
起始于的文件夹中搜索相同的内容baseUrl/node_modules
。
另外,如果找不到这些,它将搜索baseUrl/node_modules/@types
所有相同的东西。
如果仍然没有发现任何东西就开始去上一级目录和搜索node_modules
,并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
paths
不同include
?