打字稿2:非类型化的NPM模块自定义分型打字稿2:非类型化的NPM模块自定义分型(TypeScrip

2019-05-13 08:31发布

试图张贴在建议后其他地方 ,我发现自己无法得到使用非类型化的NPM模块打字稿项目的运行。 下面是一个最小的例子,我试过的步骤。

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

文件夹结构

  • node_modules
    • lodash
  • SRC
    • foo.ts
  • 分型
    • 习惯
      • lodash.d.ts
    • 全球
    • index.d.ts
  • 的package.json
  • tsconfig.json
  • typings.json

接下来,该文件。

文件foo.ts

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

console.log('Weeee');

文件lodash.d.ts直接从原来的复制@types/lodash包。

文件index.d.ts

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

文件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"
}

文件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"
  ]
}

文件typings.json

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

正如你所看到的,我已经试过进口分型的许多不同的方式:

  1. 通过直接导入它foo.ts
  2. 通过typings物业package.json
  3. 通过使用typeRootstsconfig.json与文件typings/index.d.ts
  4. 通过使用一个明确的typestsconfig.json
  5. 通过包括types目录tsconfig.json
  6. 通过使自定义typings.json文件并运行typings install

然而,当我运行打字稿:

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

我究竟做错了什么?

Answer 1:

不幸的是,这些东西目前没有很好的记录,但即使你能得到它的工作,让我们在你的配置,以便您了解每个部分在做什么,它如何与流程和负荷如何打字稿分型。

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

error TS2688: Cannot find type definition file for 'lodash'.

此错误实际上没有从您的进口或引用或您尝试在您的TS文件的任何地方使用lodash到来。 相反,它是从如何使用一个误区未来typeRootstypes的属性,所以让我们进入那些更详细一点。

关于事情typeRoots:[]types:[]性能是它们不是通用的方式来加载任意声明( *.d.ts )文件。

这两种性质直接关系到新的TS 2.0特性,它允许包装和装载打字声明从NPM包

理解这一点非常重要,那这些在NPM格式文件夹(即包含的package.jsonindex.d.ts文件夹)才能正常工作。

默认typeRoots是:

{
   "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文件夹,找到子文件夹customglobal 。 然后,它正试图解释这些作为NPM包式打字,但没有index.d.tspackage.json在这些文件夹,所以你得到的错误。

现在让我们来讨论一下的types: ['lodash']属性要设置。 这是什么呢? 默认情况下,打字稿将加载所有子文件夹找到你的内typeRoots 。 如果指定types:属性只会加载那些特定的子文件夹。

在你的情况,你告诉它加载./typings/lodash文件夹,但它不存在。 这就是为什么你会得到:

error TS2688: Cannot find type definition file for 'lodash'

因此,让我们总结一下我们所学到的。 打字稿2.0引入typeRootstypes的包装在NPM包加载声明文件。 如果有自定义分型或单松d.ts未包含withing以下NPM包约定的文件夹中的文件,那么这两个新特性是您要使用不是什么。 打字稿2.0并没有真正改变如何把这些会被消耗掉。 你只需要包含的许多标准方法之一在你的编辑内容中,这些文件:

  1. 直接包括它在一个.ts文件: ///<reference path="../typings/custom/lodash.d.ts" />

  2. 包括./typings/custom/lodash.d.ts在您的files: []属性。

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

  4. 添加./typings/**includes:

我们希望,在此基础上讨论,你就可以知道为什么狂你改变你tsconfig.json让事情再次合作。

编辑:

有一件事我忘了提的是, typeRootstypes财产,实际上只对全局声明的自动加载有用。

例如,如果您

npm install @types/jquery

而你使用的是默认tsconfig,那么该类型的jQuery包将被自动加载和$将可在所有脚本wihtout做任何进一步的///<reference/>import

所述typeRoots:[]属性是指添加从那里型封装将被装入自动frrom附加位置。

types:[]属性的主要用例是禁用自动加载的行为(将其设置为空数组),然后只列出将要在全球范围内包括特定类型。

另一种方法以从各种负载型封装typeRoots是使用新///<reference types="jquery" />指令。 注意types ,而不是path 。 再次,这是只对全局声明文件,通常是那些不这样做有用的import/export

现在,这里的引起与混乱的事情之一typeRoots 。 请记住,我说typeRoots是有关模块的全球包容性。 但@types/folder也参与了标准的模块分辨率(不管你的typeRoots设置)。

具体来说,明确导入模块总是绕过所有includesexcludesfilestypeRootstypes选项。 所以,当你这样做:

import {MyType} from 'my-module';

所有上述特性被完全忽略。 模块解决过程中的相关属性baseUrlpathsmoduleResolution

基本上,当使用node模块的分辨率,它会开始寻找一个文件名my-module.tsmy-module.tsxmy-module.d.ts开始在文件夹由您指出baseUrl配置。

如果它没有找到该文件,然后它会寻找一个文件夹名为my-module ,然后搜索package.jsontypings物业,如果没有package.json或者没有typings中,告诉它财产要加载的文件然后它将搜索index.ts/tsx/d.ts该文件夹中。

如果这仍然没有成功它将搜索在这些同样的事情node_modules文件夹开始在你baseUrl/node_modules

另外,如果没有找到这些,它会搜索baseUrl/node_modules/@types都是一样的东西。

如果仍然没有发现任何东西就开始去上一级目录和搜索node_modulesnode_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'

然后,如果没有发现它会wihtout数组中的前缀(第二项再试只是* ,这意味着最初的进口。

所以这种方式,您可以添加其他文件夹搜索报关文件,甚至定制.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



Answer 2:

编辑:过时。 看了上面的答案。

我还是不明白这一点,但我找到了解决办法。 使用以下tsconfig.json

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

删除typings.json文件夹下,一切都typings ,除了lodash.d.ts 。 同时删除所有///...引用



Answer 3:

"*": ["./types/*"]这条线在固定后2小时斗争一切tsconfig路径。

{
  "compilerOptions": {
    "moduleResolution": "node",
    "strict": true,
    "baseUrl": ".",
    "paths": {
      "*": ["./types/*"]
    },
    "jsx": "react",
    "types": ["node", "jest"]
  },
  "include": [
    "client/**/*",
    "packages/**/*"
  ],
  "exclude": [
    "node_modules/**/*"
  ]
}

类型是文件夹名称,它位于node_module即旁在客户端的文件夹(或src文件夹)的电平types/third-party-lib/index.d.ts
index.d.tsdeclare module 'third-party-lib';

注:以上配置是一个不完整的配置,只是为了给它的样子与类型的想法,路径,包括在它排除。



文章来源: TypeScript 2: custom typings for untyped npm module