【问题标题】:how do I write a typescript declaration file for module that returns class instance如何为返回类实例的模块编写打字稿声明文件
【发布时间】:2019-09-06 18:37:47
【问题描述】:

我遇到了 webpacking 不返回值的 js 模块的问题,我无计可施。所以我的方法是现在修改这些模块,使其对 typescript 和 webpack 更友好。

这里是一个例子:knockout-sortable

它将模块定义为 UMD 样式模块,但工厂函数不返回任何值。所以当我导入它时,我必须使用:

import "knockout-sortable";

typescript 正在发出导入,但 webpack 正在“优化”导入,因此模块永远不会被加载。

在内部,knockout-sortable 创建了三个类并将它们分配给 ko.bindingHandlers。从用户的角度来看,这些绑定处理程序中的每一个都有一个选项属性,我们可以在该属性上设置各种选项。所以我认为模块返回一个包含三个实例的结构会很好。我把它放在工厂函数的末尾:

return { 
   sortable: ko.bindingHandlers.sortable,
   draggable: ko.bindingHandlers.draggable,
   droppable: ko.bindingHandlers.droppable
};

我的期望是我将能够在调用代码中执行此操作:

import * as sortable from "knockout-sortable";
sortable.sortable.options = { ... };

这样,编译器和 webpack 优化器很清楚我正在使用该模块,因此它应该包含在包中。

我的问题是如何为这个模块的返回值创建类型声明文件?

这是我开始的,但是,虽然声明文件中没有错误,但我的导入语句说模块没有声明文件。 (如果我删除除了顶部的声明之外的所有内容,那么导入语句在找到声明时没有问题)。

我的 tsconfig.json 文件如下:

   {
        "compilerOptions": {
        "noImplicitAny": true,
        "noEmitOnError": true,
        "removeComments": true,
        "sourceMap": true,
        "target": "es5",
        "module": "esnext",
        "moduleResolution": "node",
        "skipLibCheck": true,
        "typeRoots": [
          "../node_modules/@types",
          "typings"
        ],
        "baseUrl": "Scripts/",
        "importHelpers": true,
        "lib": [
          "dom",
          "es5",
          "scripthost",
          "es2015.promise"
        ]
      },
      "compileOnSave": true,
    }

这是一个非常简化的 javascript 模块版本:

(function(factory) {
    if (typeof define === "function" && define.amd) {
        // AMD anonymous module
        define(["knockout", "jquery"], factory);
    } else if (typeof require === "function" && typeof exports === "object" && typeof module === "object") {
        // CommonJS module
        var ko = require("knockout"),
            jQuery = require("jquery");
        factory(ko, jQuery);
    } else {
        // No module loader (plain <script> tag) - put directly in global namespace
        factory(window.ko, window.jQuery);
    }
})(function(ko, $) {
    var sortable = 1;
    var draggable =  [];
    var  droppable = {};

    return {
        sortable: sortable,
        draggable: draggable,
        droppable: droppable
    };
});

请注意,从模块的工厂方法返回的不是构造函数,而是实际实例化的对象。如果它是构造函数,那么我会知道如何创建类型声明,但对象已经创建并在导入点返回。 (本质上这个返回的对象是一个全局的)

【问题讨论】:

    标签: typescript


    【解决方案1】:

    如果这对我有任何帮助,请评论我。如果没有,我很抱歉浪费了你的时间。这是返回公共类型的常用方法。

      return {
        // Getter Methods
        getDraggable() {
          return ko.bindingHandlers.draggable;
        },
        getSortable() {
          return ko.bindingHandlers.sortable;
        },
        getDroppable() {
          return ko.bindingHandlers.droppable;
        }
      }
    

    如果“ko”是我们的全局实例,那么工厂只返回方法(不是新的 obj 实例)。该方法返回“ko.bindingHandlers.droppable”。

    【讨论】:

    • 嗨@nikola,这并不适合我想要做的事情。我没有从模块返回一个类。我正在返回对已创建对象的引用。这些对象代表系统中的单例,所以我们不能通过构造函数创建新的。我需要 TS 知道模块的返回值就是这三个实例。
    • 也许这对你更感兴趣:github.com/zlatnaspirala/visual-ts-game-engine/blob/master/src/…。我试着帮忙,但还是不明白。
    • 不,很抱歉,这也不行。您正在考虑编写 TS 代码。但我问的是如何为一些现有的 JS 代码编写声明文件。我有 JS 代码实例化一个全局对象并从模块工厂函数返回它。我想为模块创建一个类型声明文件,告诉 TS 该模块返回一个已经实例化的对象。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-20
    • 1970-01-01
    • 1970-01-01
    • 2018-11-06
    • 2017-10-18
    相关资源
    最近更新 更多