首页 文章

当TypeScript的类型定义没有声明模块时,如何在TypeScript中导入库?

提问于
浏览
2

PeerJS具有类型定义,但它们不作为模块导出 . 它们是某些命名空间下的类型声明 .

我得到了: [ts] File 'c:/Users/Vincas/Desktop/language-exchange/node_modules/@types/peerjs/index.d.ts' is not a module.

尝试导入时: import Peer from 'peerjs' 这会尝试从类型定义导入,而不是从模块本身导入,如何从模块导入?

来自DefinitelyTyped的文件位于:https://github.com/DefinitelyTyped/DefinitelyTyped/blob/354cec620daccfa0ad167ba046651fb5fef69e8a/types/peerjs/index.d.ts

我曾经这样做过:

const PeerJS: typeof Peer = require('peerjs')
const peerjs = new PeerJS({ key: '**********' })

但这远不如: import * as Peer from 'peerjs 或类似的东西......有没有办法避免定义全局函数和全局命名空间?这对我来说看起来很糟糕 .

1 回答

  • 3

    @types/peerjs 中的已注册类型声明被指定为全局变量 . 也就是说,它们将命名空间 PeerJs 和变量 Peer 表示为全局声明(也称为"ambient") .

    declare var Peer: {
       // ...
    }
    

    这表明它们应该与可分发的库文件"dist/peer.js"一起使用,而不是与模块一起使用 . 如果要将此文件直接包含在页面中,编译器应该能够知道这些全局变量可用 .

    但实际上,您希望使用该模块 . 遗憾的是,相同的声明不兼容,必须重新编写以保证一致性 . 存储库中的旧问题保持打开状态(#176),您似乎在不久前创建了#386 . 你的直觉似乎是对的:理想情况下,有人必须适应这些声明 . 在这种情况下,由于从库中导出的对象是一个类,我们应该遵循class module模式 . 而不是 declare var Peer ,我们可以这样:

    export = Peer;
    declare class Peer {
        constructor(id: string, options?: Peer.PeerJSOption);
        constructor(options: Peer.PeerJSOption);
        // remaining methods here ...
    };
    
    declare namespace Peer {
        export interface PeerJSOption {
            // ...
        }
        // ...
    }
    

    其他接口类型放在具有相同名称的命名空间内,以便正确导出所有内容 .

    我亲自接过了这个任务:在this branch中,一个新文件"index.d.ts"被添加到了存储库,还有一些额外的package.json字段 . 这使得声明仅通过安装主依赖项工作,不需要其他包(特别是,您不应该添加"@types/peerjs") .

    你甚至可以自己尝试一下:

    的package.json:

    {
      "name": "test-peerjs-ts",
      "version": "0.1.0",
      "main": "index.ts",
      "dependencies": {
        "peerjs": "git+https://github.com/Enet4/peerjs.git#typescript-types"
      }
    }
    

    index.ts:

    import Peer = require('peerjs');
    
    let peer = new Peer("id");
    let peer2 = new Peer("id", {});
    
    type DataConn = Peer.DataConnection;
    

    您可能只会看到来自 webrtc 类型的一堆TypeScript错误,这些错误显然包含最新TypeScript编译器中已有的定义 . 仍然,编译过程将成功运行并产生良好的JavaScript代码:

    "use strict";
    exports.__esModule = true;
    var Peer = require("peerjs");
    var peer = new Peer("id");
    var peer2 = new Peer("id", {});
    

相关问题