Search code examples
typescriptthis

How to use "this" inside within writable.write function


I need to access some class instance data within a writable.write function. Here is a short snippit of typescript code that illustrates what I'm trying to do:

import * as socketio from 'socket.io'
import { Writable } from 'stream'

export class DataClient {
  public socket: socketio.Socket
  private writable: Writable

  constructor(socket: socketio.Socket) {
    this.socket = socket

    this.writable = new Writable({
      write: function (chunk, encoding, next) {
        this.socket.emit('data', chunk)
        next()
      }.bind(this),
    })
  }
}

I get the following error from ESLint:

any
'this' implicitly has type 'any' because it does not have a type annotation.ts(2683)
dataClient.ts(12, 14): An outer value of 'this' is shadowed by this container.

I've tried casting using <> and as, but that doesn't make any difference. The actual code is more complex, but this shows the problem in the simplest case. Also, while I might be able to just reference socket (the parameter), there are other instance data items that I need to access as well that are not parameters of the constructor.

Is there a way to let TS know that "this" refers to the DataClient instance?


Solution

  • You should use an arrow function to represent the write method, then this will refer to the DataClient instance:

    import * as socketio from "socket.io";
    import { Writable } from "stream";
    
    export class DataClient {
      public socket: socketio.Socket;
      private writable: Writable;
    
      constructor(socket: socketio.Socket) {
        this.socket = socket;
    
        this.writable = new Writable({
          write: (chunk, encoding, next) => {
            this.socket.emit("data", chunk);
            next();
          },
        });
      }
    }
    

    Another solution is to defie the function as a method of the class:

    import * as socketio from "socket.io";
    import { Writable } from "stream";
    
    export class DataClient {
      public socket: socketio.Socket;
      private writable: Writable;
    
      constructor(socket: socketio.Socket) {
        this.socket = socket;
    
        this.writable = new Writable({
          write: this.writeFunc,
        });
      }
    
      writeFunc(chunk: any, encoding: BufferEncoding, next: any): void {
        this.socket.emit("data", chunk);
        next();
      }
    }