Node.js 使用TypeScript正确扩展stream.Transform类

Node.js 使用TypeScript正确扩展stream.Transform类,node.js,typescript,tsc,typescript3.0,Node.js,Typescript,Tsc,Typescript3.0,我有以下代码: import * as stream from 'stream'; export class JSONParser extends stream.Transform { lastLineData = ''; objectMode = true; constructor() { super(); } transform(chunk, encoding, cb) { let data = String(chunk); i

我有以下代码:

import * as stream from 'stream';    

export class JSONParser extends stream.Transform {

  lastLineData = '';
  objectMode = true;

  constructor() {
    super();

  }

  transform(chunk, encoding, cb) {

    let data = String(chunk);
    if (this.lastLineData) {
      data = this.lastLineData + data;
    }

    let lines = data.split('\n');
    this.lastLineData = lines.splice(lines.length - 1, 1)[0];

    lines.forEach(l => {
      try {
        // l might be an empty string; ignore if so
        l && this.push(JSON.parse(l));
      }
      catch (err) {
        // noop
      }
    });

    cb();

  }

  flush(cb) {
    if (this.lastLineData) {
      try {
        this.push(JSON.parse(this.lastLineData));
      }
      catch (err) {
        // noop
      }
    }
    this.lastLineData = '';
    cb();
  }


}
问题是TS类型不能识别(原型)方法。我是否错误地扩展了Transform类

问题是:

请注意,这是正确的:

import * as stream from 'stream';

//////////////////////////////////////////////////

export interface IParsedObject {
  [index: string]: any
}

export const createParser = function () {

  let lastLineData = '';

  return new stream.Transform({

    objectMode: true,

    transform(chunk: any, encoding: string, cb: Function) {

      let data = String(chunk);
      if (lastLineData) {
        data = lastLineData + data;
      }

      let lines = data.split('\n');
      lastLineData = lines.splice(lines.length - 1, 1)[0];

      lines.forEach(l => {
        try {
          // l might be an empty string; ignore if so
          l && this.push(JSON.parse(l));
        }
        catch (err) {
          // noop
        }
      });

      cb();

    },

    flush(cb: Function) {
      if (lastLineData) {
        try {
          this.push(JSON.parse(lastLineData));
        }
        catch (err) {
          // noop
        }
      }
      lastLineData = '';
      cb();
    }
  });

};

但是上面的类似乎工作不一样。

好的,现在它似乎工作了,我必须将构造函数选项传递给
super()
,所以它变成
super({objectMode:true})


剩下的唯一问题是我应该实现
\u flush()
还是
flush()
,我不确定…我现在实现了这两个…

在您的屏幕截图中,您试图扩展
Transform
类,但您没有实现正确的方法,您应该实现
Transform.\u Transform(区块,编码,回调)
,则typescript将自动推断所需的类型。由于
转换上不存在
转换
类型typescript没有用于推断的类型,因此编译器生成警告

在代码示例中,您选择使用“简化”
Transform
构造函数。构造函数采用一组选项,允许您定义必要的转换方法,而无需显式扩展类。这些选项选择非下划线前缀命名约定,但在扩展类时,它们与下划线前缀方法等效。因为您使用了方法的正确名称此处可以推断类型


Transform
API调用了三种方法的实现,下面对这些方法进行了概述

有两种方法可以实现
转换
流:

  • 扩展
    转换
  • 使用
    转换
    构造函数 选项
  • 概述了这两种方法(包括在ES6之前的环境中扩展类的示例)


    在实现
    转换时
    流只能实现一种方法:

  • transform.\u转换(块、编码、回调)
  • 其他两种方法是可选的,如果用例需要,可以实现:

  • transform.\u刷新(回调)
  • 可写。_final(回调)

  • 我已经在下面概述了文档化的
    Transform
    方法,突出了一些可能感兴趣的领域

    应用程序代码不能直接调用此函数。它 应该由子类实现,并由内部 仅可读类方法。

    在某些情况下,变换操作可能需要发出额外的 流末尾的数据位。例如,zlib压缩 流将存储一定数量的内部状态,用于优化 压缩输出。但是,当流结束时,额外的 需要刷新数据,以便完成压缩数据

    自定义转换实现可以实现转换。_flush() 方法。当没有更多的写入数据时,将调用此方法 已消耗,但在发出“结束”事件之前,发出结束的信号 可读流

    在transform._flush()实现中,可读的.push() 方法可能被调用零次或多次(视情况而定) 函数必须在刷新操作完成时调用

    transform.\u flush()方法的前缀为下划线,因为 它是定义它的类的内部,永远不应该是 由用户程序直接调用。

    应用程序代码不能直接调用此函数。它 应该由子类实现,并由内部 仅可读类方法。

    所有转换流实现都必须提供一个_Transform() 方法接受输入并生成输出。转换。_transform() 实现处理正在写入的字节,计算输出, 然后使用 readable.push()方法

    可以零次或多次调用transform.push()方法来 从单个输入块生成输出,具体取决于要输入的数据量 将被输出为块的结果

    任何给定的数据块都可能不会生成任何输出 输入数据

    仅当当前块为空时,才能调用回调函数 已完全使用。传递给回调的第一个参数必须为 如果在处理输入或输出时发生错误,则为错误对象 否则为null。如果将第二个参数传递给回调,则 将转发到可读的.push()方法 以下是等效的:

    转换。_transform()方法的前缀是 使用下划线,因为它是定义 用户程序不应直接调用它。

    transform.\u transform()从不并行调用;流实现 一个队列机制,要接收下一个块,回调必须是 以同步或异步方式调用

    不能直接调用_final()方法。它可以实现 由子类调用,如果是,将由内部可写 仅类方法。

    此可选函数将在流关闭之前调用, 延迟“完成”事件直到调用回调。这很有用 在流结束前关闭资源或写入缓冲数据


    流API有详尽的文档。您可以找到实现所需的方法,还可以找到有关实现
    Transform
    streams的具体细节。@JakeHolzinger不够全面,是吗
    export class JSONParser extends stream.Transform {
    
      lastLineData = '';
    
      constructor() {
        super({objectMode: true});
    
      }
    
      _transform(chunk: any, encoding: string, cb: Function) {
    
        let data = String(chunk);
        if (this.lastLineData) {
          data = this.lastLineData + data;
        }
    
        let lines = data.split('\n');
        this.lastLineData = lines.splice(lines.length - 1, 1)[0];
    
        lines.forEach(l => {
          try {
            // l might be an empty string; ignore if so
            l && this.push(JSON.parse(l));
          }
          catch (err) {
            // noop
          }
        });
    
        cb();
    
      }
    
      flush(cb: Function) {
        if (this.lastLineData) {
          try {
            this.push(JSON.parse(this.lastLineData));
          }
          catch (err) {
            // noop
          }
        }
        this.lastLineData = '';
        cb();
      }
    
      _flush(cb: Function) {
        if (this.lastLineData) {
          try {
            this.push(JSON.parse(this.lastLineData));
          }
          catch (err) {
            // noop
          }
        }
        this.lastLineData = '';
        cb();
      }
    
    }
    
    transform.prototype._transform = function(data, encoding, callback) {
      this.push(data);
      callback();
    };
    
    transform.prototype._transform = function(data, encoding, callback) {
      callback(null, data);
    };