为外部 js nodejs 包编写 typescript 声明文件,没有类型信息

Posted

技术标签:

【中文标题】为外部 js nodejs 包编写 typescript 声明文件,没有类型信息【英文标题】:Writing a typescript declaration file for an external js nodejs package, without type info 【发布时间】:2020-02-19 21:06:21 【问题描述】:

我正在编写一个节点 js 打字稿库(用于 cli 应用程序上下文),它依赖于一个 js 库 jinxed,它没有打字稿类型声明。我一直在Typescript declaration files关注信息

jinxed 是一个简单的库,目前通过 module.exports ... 导出单个函数,它不打算作为库的唯一导出,(因为它将被扩展将来)。所以导出的函数是导出对象的成员。

问题是我如何在打字稿库中使用它。在阅读了所有的打字稿声明文档之后,我仍然不清楚如何做到这一点。

要解决的第一个问题是从Typescript declaration file templates 中选择哪个声明模板。

我决定用于从 typescript 消费 jinxed 的适当模板是 module.d.ts(不过我会更正)。

所以我的客户端打字稿库(小部件)看起来像这样:

widget/
  lib/
    externalTypes/
      jinxed/
        index.d.ts
    index.ts

所以上面显示了我根据模板文件中的说明为外部依赖项定义了一个类型文件;即创建一个名称与外部依赖的名称匹配的文件夹,并在其中放置一个 index.d.ts 文件。

widget/lib/externalTypes/jinxed/index.d.ts:

导出函数functify(obj: any): string;

在消费方面;即在我的 index.ts 文件中(小部件/lib/index.ts):

/// <reference types="./externalTypes/jinxed" />

import jinxed = require('jinxed');

const TestObject:any = 
  name: 'dvorak',
  occ: 'watchman'
;

jinxed.functify(TestObject);

[PS:我也试过了:

让 jinxed = require('./externalTypes/jinxed'); ( ... 但这只会导致使用 require 语句时出错)

]

但是编译的时候会出现如下错误信息:

/Users/User/dev/github/js/widget/lib/index.ts 中的错误 ./lib/index.ts [tsl] 错误在

/Users/User/dev/github/js/widget/lib/index.ts(4,25) TS7016:找不到模块“jinxed”的声明文件。 '/Users/User/dev/github/js/widget/node_modules/jinxed/index.js' 隐式具有“任何”类型。

(对于错误信息看起来有点难看,格式问题表示歉意)

[

为了完整起见,jinxed的内容如下:

'use strict';

function functify (obj) 
  return JSON.stringify(obj, (key, val) => 
    return (typeof val === 'function') ? '_function_' : val;
  );


module.exports = 
  functify: functify

]

报错提示找不到jinxed的声明文件,但是我用过

 /// <reference...

指定要使用的type文件,所以不知道是什么问题。

widget package.json 中的依赖如下:

  "dependencies": 
    "@types/ramda": "^0.26.19",
    "jinxed": "0.0.1",
    "ramda": "^0.26.1",
    "xpath": "0.0.27"   ,

tsconfig 文件是:


  "compilerOptions": 
    "allowJs": true,
    "alwaysStrict": true,
    "module": "commonjs",
    "moduleResolution": "Node",
    "noImplicitAny": true,
    "sourceMap": true,
    "strictNullChecks": true,
    "target": "es5",
    "types": [],
    "lib": [
      "es5",
      "es2015",
      "es6",
      "dom"
    ]
  ,
  "include": [
    "lib/**/*"
  ],
  "exclude": [
    "node_modules",
    "**/*.spec.ts"
  ]

package.json 中的“main”条目是:

"main": "./lib/index.ts",

另外,我想知道我构建外部类型依赖项的方式是否合理。 IE,比方说,我正在尝试以与上述 jinxed 类似的方式使用另一个外部 js 库;我会假设,我会在 externalTypes 下创建另一个与该依赖项名称匹配的文件夹,并用它自己的 index.d.ts 填充它。这是正确的还是我找错了树?

编辑:(我通过this issue 找到了解决此问题的方法,但我并不真正理解这一点。

在 index.d.ts 中,我已将其更新为如下:

declare module 'jinxed' 
  export function functify(obj: any): string;

...这确实有效。

但是,我不明白 declare module 语句,特别是为什么名称 jinxed 在引号内(删除引号会出现错误:TS7016 : 找不到模块 'jinxed' 的声明文件)。到目前为止,我还没有找到与之对应的正确打字稿模板,所以我无法很好地解释为什么会这样。

【问题讨论】:

【参考方案1】:

您似乎找到了原始问题的答案,但我想我会分享一些有关您的第二个问题的资源。来自打字稿文档:Ambient Modules

在 Node.js 中,大多数任务都是通过加载一个或多个模块来完成的。我们可以使用***导出声明在自己的 .d.ts 文件中定义每个模块,但将它们写成一个更大的 .d.ts 文件更方便。为此,我们使用类似于环境命名空间的构造,但我们使用 module 关键字和模块的引用名称,这些名称将在以后的导入中可用。

declare module 是语言关键字,字符串是您要导入的模块的名称。

【讨论】:

太棒了 Donovan,这正是我一直在寻找的,只是很容易在正确的时间找不到正确的正确信息。我最初使用 externalTypes//index.d.ts 的方法是阅读模板的结果,事实证明,这不是我应该寻找的解决方案。干杯。

以上是关于为外部 js nodejs 包编写 typescript 声明文件,没有类型信息的主要内容,如果未能解决你的问题,请参考以下文章

nodejs小问题:[1]express不是内部或外部命令

如何在docker里部署nodejs

nodejs第三天(核心模块与文件模块,核心模块和文件模块引入的区别,从模块外部访问模块内部,使用exports对象,npm包管理工具package.json文件,模块对象属性,将模块定义分类,npm

NodeJS Rest API - 调用外部 API 的正确位置在哪里

node.js ----NPM使用介绍

Nodejs中前后端分离