我正在用TS建造一个图书馆.该库使用ssh2库作为依赖项.

我正在try 创建一个函数,该函数既可以接受ssh2配置对象,也可以接受现有的Client实例来执行命令(这是一个简化的情况):

import { Client, ConnectConfig } from 'ssh2';

export function runCommand(params: Client | ConnectConfig) {
  if(params instanceof Client) {
    // do something
  } else {
    // create our own client
    // do something
  }
}

当我构建这个库并调用函数时,如下所示:

const { readFileSync } = require("fs");
const { Client } = require("ssh2");
const { runCommand } = require("myLib");
const conn = new Client();

conn
  .on("ready", () => {
    console.log("Client :: ready");
    runCommand(conn);
  })
  .connect({
    host: "example.com",
    port: 22,
    username: "me",
    privateKey: readFileSync(process.env.HOME + "/.ssh/id_ed25519"),
  });

由于某些原因,我的函数中的instanceof签入将返回false.这里到底发生了什么?是TS编译问题,还是Node.js将我的库的依赖项和消费者代码的依赖项中的Client视为两个不同的类?

编译后的代码类似于:

const ssh2_1 = require("ssh2");
//...
function runCommand(params) {
    if (params instanceof ssh2_1.Client) {
        // do something
    }
    else {
       // create our own client
    // do something
    }
}

推荐答案

instanceof操作符的行为来看,可能不明显的是,类必须是父链中的exactly,从JavaScript对象reference的意义上讲.

因此,如果您两次导入Client个类,它们是不同的实际对象引用,instanceof可能会给出"假"否定.

这很可能就是这里发生的事情:ssh2与您的库Bundle 在一起,因此它导入了自己的依赖项副本.而你的应用程序本身就导入了ssh2个,导致了separate个副本.

您有几个选项:

  • 不要将依赖项与您的库Bundle 在一起(例如使用webpack externals),让应用程序安装您的库和应用程序都将导入的single版本;指定peerDependencies的典型情况
  • 不要使用instanceof运算符;而是使用一些启发式方法来确定对象是否具有所需的形状;通常会判断某些属性及其类型
  • 从您的库中重新导出依赖项(例如,在您的库中为Client个类),并在您的应用程序(const { Client, runCommand } = require("myLib");)中使用该依赖项,这样它就是完全相同的副本(既然它已经Bundle 在一起了,为什么不重新使用它而不是重新Bundle 它呢?)

Javascript相关问答推荐

如何指定1条记录1个表?

*ngFor和@代表输入decorator 和选角闭合

了解Node.js中的EventEums和浏览器中的addEventEums之间的关系

Angular中计算信号和getter的区别

Snowflake JavaScript存储过程返回成功,尽管预期失败

嵌套异步JavaScript(微任务和macrotask队列)

函数返回与输入对象具有相同键的对象

如何将Openjphjs与next.js一起使用?

你怎么看啦啦队的回应?

为什么按钮会随浮动属性一起移动?

获取Uint8ClampedArray中像素数组的宽度/高度

JS—删除对象数组中对象的子对象

编剧如何获得一个div内的所有链接,然后判断每个链接是否都会得到200?

当我try 将值更改为True时,按钮不会锁定

在VS代码上一次设置多个变量格式

按什么顺序接收`storage`事件?

无法重定向到Next.js中的动态URL

使用RxJS from Event和@ViewChild vs KeyUp事件和RxJS主题更改输入字段值

如何更改Html元素S的 colored颜色 ,然后将其褪色为原始 colored颜色

递增/递减按钮React.js/Redux