René
René

Reputation: 31

Node.js process.stdin issues with typescript (tty.ReadStream vs ReadableStream)

I've used some javascript code like this to catch user inputs in Node.js:

if (process.stdin.isTTY) {
  process.stdin.setRawMode(true)
  process.stdin.setEncoding('utf8')
  process.stdin.resume()    

  // safe shutdown if key 'q' is pressed
  process.stdin.on('data', key => {
    if (key === 'q') {
      console.log('quit')
      ...
      process.exit()
    }
  })
}
...

This works fine. Now, I try to do the same in TypeScript, but here, when I try to transpile the code I get the error:

error TS2339: Property 'setRawMode' does not exist on type 'ReadableStream'.

So, I've changed the code a little bit, I've encapsulated everything in a class with the correct type for my stdin property:

import * as tty from 'tty'

class MyClass {
  private stdin: tty.ReadStream

  constructor() {
    this.stdin = process.stdin
  }

  exec() {
    if (this.stdin.isTTY) {
      this.stdin.setRawMode(true)
      this.stdin.setEncoding('utf8')
      this.stdin.resume()    

      // safe shutdown if key 'q' is pressed
      this.stdin.on('data', (key:string) => {
        if (key === 'q') {
          console.log('quit')
          ...
          process.exit()
        }
      })
    }
    ...
  }
}

const myClass = new MyClass()

myClass.exec()

Since my class property stdin is of type tty.ReadStream the previously unknown method setRawMode is known, but now, the assignment in the constructor fails with:

error TS2322: Type 'ReadableStream' is not assignable to type 'ReadStream'. Property 'isRaw' is missing in type 'ReadableStream'.

So, what I'm doing wrong? How can I solve this? Again, in JavaScript everything works fine.

I'm using Node.js 7.5.0, TypeScript 2.1.5, @types/node 7.0.5 on ARMv7 (Raspberry Pi2)

Upvotes: 3

Views: 2925

Answers (3)

dthusian
dthusian

Reputation: 378

I don't know if this is a bit late, but this also compiles:

import * as tty from "tty";
if(process.stdin instanceof tty.ReadStream){
  process.stdin.setRawMode(true);
}

Upvotes: 2

T. Junghans
T. Junghans

Reputation: 11683

An easy solution is to assign the any type to stdin:

const stdin: any = process.stdin;

Trying to set the correct type or applying Type assertion to process.stdin led to further TypeScript errors (just like you describe in your question).

It seems to me that Typescript cannot handle process.stdin being two different types, either net.Socket or Readable, see the docs:

The process.stdin property returns a stream connected to stdin (fd 0). It is a net.Socket (which is a Duplex stream) unless fd 0 refers to a file, in which case it is a Readable stream.

It would be great to know what the correct solution is.

Upvotes: 3

Robert Hurst
Robert Hurst

Reputation: 26

Ran into the same issue; upgraded to latest node v6.10. Its API documentation is a bit hairy, but I managed to get my code corrected for build and run:

const tty = require('tty')
if (tty.isatty(0))
    tty.ReadStream().setRawMode(true)

See a working example: npm install xvt

Upvotes: 0

Related Questions