使用TypeScript

时间:2018-09-18 17:25:27

标签: 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);
    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类?

问题出在这里

enter image description here

请注意,这是正确的:

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();
    }
  });

};

但是上面的类似乎工作方式不同。

2 个答案:

答案 0 :(得分:1)

好了,现在看来它可以工作了,我不得不将构造函数选项传递给super(),所以它变成了super({objectMode:true})

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();
  }

}

剩下的唯一问题是我应该执行_flush()还是flush(),我不确定...我现在都实现了...

答案 1 :(得分:1)

在屏幕快照中,您尝试扩展Transform类,但未实现正确的方法,应实现transform._transform(chunk, encoding, callback),然后typescript将自动推断所需的类型。由于transform.transform(chunk, encoding, callback)类型上不存在Transform,因此typescript没有可用于推断的类型,因此编译器会生成警告。

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


Transform API要求实现三种方法,here概述了这些方法。

有两种方法可以实现Transform流:

  1. 扩展Transform
  2. 使用Transform构造函数 选项。

here概述了这两种方法(包括在ES6之前的环境中扩展类的示例)。


实现Transform流时,只能实现一种方法:

  1. transform._transform(chunk, encoding, callback)

其他两种方法是可选的,并且在用例需要时可以实现:

  1. transform._flush(callback)
  2. writable._final(callback)

我已经继续并概述了下面记录的Transform方法,重点介绍了一些可能令人感兴趣的领域。

transform._flush(callback)

  

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

     

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

     

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

     

在transform._flush()实现中,read.push()   该方法可以视情况被称为零次或多次。回调   刷新操作完成后必须调用该函数。

     

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

transform._transform(chunk, encoding, callback)

  

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

     

所有Transform流实现都必须提供_transform()   接受输入并产生输出的方法。 transform._transform()   实现处理正在写入的字节,计算输出,   然后使用将该输出传递给可读部分   visible.push()方法。

     

transform.push()方法可能被调用零次或更多次以   从单个输入块生成输出,具体取决于要输入多少   作为块的结果被输出。

     

很可能没有任何给定的块生成任何输出   输入数据。

     

仅当当前块为   完全消耗。传递给回调的第一个参数必须为   如果处理输入时发生错误,则返回一个Error对象,或者   否则返回null。如果将第二个参数传递给回调,则它将   将被转发到可读.push()方法。换句话说   以下是等效的:

transform.prototype._transform = function(data, encoding, callback) {
  this.push(data);
  callback();
};

transform.prototype._transform = function(data, encoding, callback) {
  callback(null, data);
};
  

transform._transform()方法带有前缀   带下划线,因为它在定义该类的内部   它,绝对不能由用户程序直接调用。

     

transform._transform()永远不会并行调用;流实现   队列机制,并且要接收下一个块,回调必须为   同步或异步调用。

writable._final(callback)

  

不得直接调用_final()方法。可以实施   由子类,如果是,则由内部Writable调用   仅限类方法。

     

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