TypeScript 2:非类型化 npm 模块的自定义类型

2023-12-13

尝试后发布的建议其他地方,我发现自己无法运行使用非类型化 NPM 模块的打字稿项目。下面是一个最小的示例和我尝试的步骤。

对于这个最小的例子,我们假设lodash没有现有的类型定义。因此,我们将忽略该包@types/lodash并尝试手动添加其打字文件lodash.d.ts到我们的项目。

文件夹结构

  • node_modules
    • lodash
  • src
    • foo.ts
  • typings
    • custom
      • 洛达什.d.ts
    • global
    • 索引.d.ts
  • 包.json
  • tsconfig.json
  • 打字.json

接下来,文件。

File foo.ts

///<reference path="../typings/custom/lodash.d.ts" />
import * as lodash from 'lodash';

console.log('Weeee');

File lodash.d.ts是直接从原文复制的@types/lodash包裹。

File index.d.ts

/// <reference path="custom/lodash.d.ts" />
/// <reference path="globals/lodash/index.d.ts" />

File package.json

{
  "name": "ts",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "typings": "./typings/index.d.ts",
  "dependencies": {
    "lodash": "^4.16.4"
  },
  "author": "",
  "license": "ISC"
}

File tsconfig.json

{
  "compilerOptions": {
    "target": "ES6",
    "jsx": "react",
    "module": "commonjs",
    "sourceMap": true,
    "noImplicitAny": true,
    "experimentalDecorators": true,
    "typeRoots" : ["./typings"],
    "types": ["lodash"]
  },
  "include": [
    "typings/**/*",
    "src/**/*"
  ],
  "exclude": [
    "node_modules",
    "**/*.spec.ts"
  ]
}

File typings.json

{
    "name": "TestName",
    "version": false,
    "globalDependencies": {
        "lodash": "file:typings/custom/lodash.d.ts"
    }
}

正如您所看到的,我尝试了许多不同的导入类型的方法:

  1. 通过直接导入foo.ts
  2. By a typings财产在package.json
  3. 通过使用typeRoots in tsconfig.json有一个文件typings/index.d.ts
  4. 通过使用显式types in tsconfig.json
  5. 通过包括types目录在tsconfig.json
  6. 通过定制typings.json文件并运行typings install

然而,当我运行 Typescript 时:

E:\temp\ts>tsc
error TS2688: Cannot find type definition file for 'lodash'.

我究竟做错了什么?


不幸的是,这些事情目前没有很好的记录,但即使您能够让它工作,让我们检查一下您的配置,以便您了解每个部分正在做什么以及它与打字稿如何处理和加载打字的关系。

首先让我们回顾一下您收到的错误:

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 并没有真正改变它们的使用方式。您只需以多种标准方式之一将这些文件包含在您的编译上下文中:

  1. 直接将其包含在.ts file: ///<reference path="../typings/custom/lodash.d.ts" />

  2. 包括./typings/custom/lodash.d.ts在你的files: []财产。

  3. 包括./typings/index.d.ts在你的files: []属性(然后递归地包含其他类型。

  4. 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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

TypeScript 2:非类型化 npm 模块的自定义类型 的相关文章

随机推荐

  • 当物品完成重新绘制时我可以收到通知吗?

    我正在制作快照 通过ShaderEffectSource with live false 的项目 但我有时 200 例中有 1 例 得到空白快照 我正在根据这样的信号制作快照 Image onStatusChanged if status
  • 用户注册后创建产品

    用户注册后是否可以自动创建产品 我正在创建一种市场 因此当用户注册为供应商时 我希望 Woocommerce 自动创建具有以下规格的产品 产品名称 预订 the author meta display name 产品块 日历 the aut
  • 反序列化时如何以字符串形式获取 XML 节点值

    我正在将 XML 发送到 aspnet core web api 命名空间前缀的值cfdi 定义在包含节点中
  • 从 ListView 到其父级的冒泡滚动事件

    在我的 WPF 应用程序中 我有一个ListView whose ScrollViewer VerticalScrollBarVisibility被设定为Disabled 它包含在一个ScrollViewer 当我尝试在ListView 外
  • 读取 HttpURLConnection InputStream - 手动缓冲区或 BufferedInputStream?

    读取 HttpURLConnection 的 InputStream 时 是否有理由使用以下其中一项而不是另一个 我已经在示例中看到了两者的使用 手动缓冲器 while length inputStream read buffer gt 0
  • Firefox 中的日期问题

    我想将页面中的日期解析为 JavascriptDate 所以我的页面中有这个 span 01 07 2012 01 04 PM span 我有 Javascript 代码可以解析迄今为止的这个值 var tagText this html
  • 如果在 JFrame 之外,Java 中的工具提示会闪烁吗?

    我正在 Java 中实现 ToolTip 以便让用户更轻松地使用该产品 尽管位于 JFrame 边界并最终位于 JFrame 外部的工具提示开始 闪烁 我已经尝试了很多东西 比如移动工具提示 使其应该位于 Jframe 内 控制绘画 使其最
  • R中绘图的最佳拟合曲线

    我在一个名为 ph 的图中有一个概率密度函数 它是在 stackoverflow 用户的帮助下从两个数据样本中得出的 以这种方式 few lt read table outcome dat head TRUE many lt read ta
  • D3.js 组件中的样式未显示在 Angular 2 中

    我正在使用 Angular 2 和 D3 js 我想显示一个红色矩形 仅当我将样式放入样式 css文件 查看这个笨蛋 当我将样式放入组件中时styles 这是行不通的 查看这个笨蛋 当我使用组件时如何让它工作styles Thanks UP
  • 向 Windows Phone 7 模拟器添加更多音乐?

    模拟器有大约 3 首歌曲 这不足以确保我正在开发的歌曲选择代码能够管理超过上述 3 首歌曲 所以只是想知道这是否可能 不幸的是 无法将歌曲添加到模拟器中 您必须使用真实设备来测试这一点
  • 如何用括号外的逗号分割字符串?

    我得到了这样格式的字符串 Wilbur Smith Billy son of John Eddie Murphy John Elvis Presley Jane Doe Jane Doe 所以基本上它是演员姓名列表 可选地在括号中加上他们的
  • 当源文件路径更改时,如何保持项目的数据库连接?

    我正在使用一个微软Access数据库在我的项目中 保存到bin文件夹 当文件路径更改时 我该怎么做才能确保与该数据库的连接 导入 System Data OleDb 公开课Form3 Dim con 作为新的 OleDb OleDbConn
  • 在所有库中导入应用程序兼容性依赖项

    我的应用程序中有 2 个模块 我想修改它们以使用 AppCompat 小部件 我必须用相同的方式扩展它们 问题是我不想向它们中的每一个添加 appcompat 依赖项 那么我怎么可能向这两个模块和我的应用程序添加依赖项 如果我添加 comp
  • 如何防止点击标签时页面刷新?

    我需要将一个参数传递到 URL 中 同时阻止页面在单击任何一个时重新加载 a 带有空白的标签href属性 a href 有没有办法用 JS jQuery 来做到这一点 我已经有了这个 jQuery list group item a cli
  • SQL 计数和组

    我有一个与此类似的 MySQL db 表 id date class more info one more info two etc 1 2017 05 03 1 2 2017 05 03 3 3 2017 05 11 1 4 2017 0
  • 在客户端验证行比使用整个主键的二级索引更好?

    在 cassandra 中 众所周知 应该非常谨慎地使用二级索引 例如 如果我有一张桌子 User username usertype email etc 这里的用户名是分区键 现在我想支持当且仅当 usertype 是特定值 X 时返回特
  • 接收方未注册异常错误?

    在我的开发者控制台中 人们不断报告一个错误 我无法在我拥有的任何手机上重现该错误 一个人留言说 当他们尝试打开我的电池服务的设置屏幕时 他收到了消息 正如您从错误中看到的 它表明接收器未注册 java lang RuntimeExcepti
  • Facebook API:所有朋友共享的所有链接?

    访问所有用户 Facebook 好友共享的链接的最实用方法是什么 我希望抓取由经过身份验证的用户的朋友共享的少数域的所有链接 有没有办法询问 域 X 的所有链接 所有链接 我将过滤域 X 或者我是否需要获取每个朋友并解析每个单独的提要 我假
  • T-SQL 读取带有命名空间的 xml 文件

    我尝试读取 sql server 中的 xml 文件 DECLARE XMLToParse XML Load the XML data in to a variable to work with This would typically b
  • TypeScript 2:非类型化 npm 模块的自定义类型

    尝试后发布的建议其他地方 我发现自己无法运行使用非类型化 NPM 模块的打字稿项目 下面是一个最小的示例和我尝试的步骤 对于这个最小的例子 我们假设lodash没有现有的类型定义 因此 我们将忽略该包 types lodash并尝试手动添加