您如何为包含多个模块/类的“复杂”香草 JavaScript 库编写工作 .d.ts 文件?

Posted

技术标签:

【中文标题】您如何为包含多个模块/类的“复杂”香草 JavaScript 库编写工作 .d.ts 文件?【英文标题】:How do you write a working .d.ts file for a "complex" vanilla javascript library containing multiple modules/classes? 【发布时间】:2021-10-23 10:13:17 【问题描述】:

我正在尝试将 javascript 项目转换为打字稿。这个项目依赖于一个普通的 javscript 库/模块,没有可用的官方类型声明,这意味着我必须自己编写。

目前我的项目导入库如下:

const lib = require('library-name')

该库模块中包含的所有模块/类都按如下方式导入:

const module = lib.module

编译器没有报告导入错误,当我以这种形式编写我的 .d.ts 文件时也没有报告错误(对于非对象模块):

  declare module 'library-name' 
    ...
    declare module 'module1' 
      function functionName: functionType;
    
    ...
  

然而,其中一些模块也是 OBJECT CLASSES - 换句话说,可以使用 `new class()' 创建它们的实例。我尝试将它们声明如下:

  declare module 'library-name' 
    declare module class_module
      class class_module 
        function1(parameter: type): functionType;
        function2(): void;
          
    
      export = class_module;
    
  

当我尝试将变量或常量键入为 class_module 类型时,即

    let var: class_module = something;

我收到一条错误消息,提示“'class_module' 指的是一个值,但在这里被用作一个类型。”我已经三重检查以确保将其导入 .ts 文件并在 .d.ts 文件中以与所有其他模块完全相同的方式声明它。

为了让事情更混乱,有一个类不会发生这种情况 - 当我使用它来键入常量或变量时编译器不会抱怨。但是,我不能使用该类的任何函数,因为我总是得到一个错误:

此表达式不可调用。类型“typeof ObjectName”没有调用 签名。

我不知道这是否相关,但所有其他给出关于将值用作类型的错误的类都使用“导出模块”,而没有抛出此错误的类使用更晦涩和陌生的 (对我来说)语法,以

开头的文件
  (function(exports) 
and ending with
  exports.ClassName = ClassName;
  )(typeof exports !== 'undefined' ? exports : this);

每个模块的导出方式重要吗?

我尝试过各种方式的切换、导入和声明模块的方式不同:

使用“import module1, module2, ... module n from 'module'” 将模块声明为命名空间、接口、类(直接),你在 .d.ts 中有什么 ... 以及在黑暗中拍摄的各种其他照片。似乎没什么大不了的。

【问题讨论】:

【参考方案1】:

您可以将class_module 定义为一个类,然后使用命名空间对其进行扩展:

declare module 'library-name' 
  declare namespace class_module 
    export = class_module
  

  declare class class_module 
    function1(parameter: type): functionType
    function2(): void
  

使用模块:

import class_module from 'library-name'
// or
import lib from 'library-name'
const class_module = lib
type class_module = lib.class_module

const foo: class_module = new class_module()

另见(来自 TypeScript 手册):

Modules.d.ts: Namespaces in Module Code Module: Class .d.ts template

【讨论】:

这行得通。嗯,它的一部分。声明命名空间什么也没做。 “import class_module from 'library-name'什么也没做。但是,第三部分——即使没有前两个(“import lib from 'library-name'...type class_module = lib.class_module”)把戏。我猜这行得通,因为它明确地将模块声明为一种类型? 虽然这有效,但感觉就像一个“hacky”解决方案。这通常被认为是好的做法吗? 为了让 eslint 停止抱怨我的代码中其他与打字稿相关的事情,我不得不做一些其他的事情。

以上是关于您如何为包含多个模块/类的“复杂”香草 JavaScript 库编写工作 .d.ts 文件?的主要内容,如果未能解决你的问题,请参考以下文章

您如何为视图填充的变化设置动画?

您如何为委托参数提供 xml 注释/文档?

您如何为 webgl 应用程序创建验收测试?

您如何为 ORM 的分页定义中继连接?

您如何为 Google Cloud 平台签署 HIPAA BAA?

您如何为 Stripe 结帐会话生成付费发票 PDF?